<?php

/*
=====================================================
 File: mod.ncb_rooms.php
-----------------------------------------------------
 Purpose: NCB Metting room booking form & calendar class
=====================================================

The calendar view of this class was adapted from the standard weblog calendar
(this provides the meeting room calendar functionality only).

See example template files for usage:

- booking_form_template.html
- meeting_views_template.html

There are two main functions:

booking_form() - handles the display and processing of bookings

calendar() - outputs the various views: day_view/week_view/rooms_view/calendar_view
(these are controlled by URL/form parameters e.g. action=rooms_view)

There are different tag pairs to use for formatting the output of the different views, e.g.

##### Meetings/calendar output #####

{exp:ncb_rooms:calendar booking_script_url="<url to page containing booking form>" <parameters...>}
    ...
	{calendar_view}
	     ...
	    <formatting and other EE tags - see example template file>
		 ...
	{/calendar_view}

	{day_view}
	     ...
	    <formatting and other EE tags>
		 ...
	{/day_view}
    ...
	{week_view}
	     ...
	    <formatting and other EE tags>
		 ...
	{/week_view}
	...
	{rooms_view}
	     ...
	    <formatting and other EE tags>
		 ...
	{/rooms_view}
	...
	{rooms_list}
	     ...
	    <formatting and other EE tags>
		 ...
	{/rooms_list}
	...

 {/exp:ncb_rooms:calendar}

#### Booking form output ######

{exp:ncb_rooms:booking_form}
	{errors}

	<p>Booking on: <strong>{booking_date}</strong></p>

	<table width="100% border="1" cellpadding="4" cellspacing="0">
		<tr><td>Meeting name:</td><td>{field_meeting_name}</td></tr>
		<tr><td>Start time:</td><td>{field_start_time_hours} : {field_start_time_minutes}</td></tr>
		<tr><td>Duration:</td><td>{field_duration_minutes} </td></tr>
		<tr><td>Room:</td><td>{field_room} </td></tr>
		<tr><td>Booking owner: </td><td>{booking_owner} </td></tr>
		<tr><td colspan="2" align="center">{field_submit_ok value="Book room" style="width: 80px"} {field_submit_cancel value="Cancel"  style="width: 80px"}</td></tr>
	</table>
{/exp:ncb_rooms:booking_form}

**** All unused (unreplaced) EE tags will be stripped out. *****

*/

if ( ! defined('EXT'))
{
    exit('Invalid file request');
}

error_reporting(E_ALL ^ E_NOTICE); // TMP turn off notices


class Ncb_rooms extends Weblog {

    var $return_data = '';
	var $referer = '';

	var $earliest_slot_hour = "07";
	var $latest_slot_hour = "21";

	// for room booking
	var $booking_id = array();
	var $settings = array();
	var $rooms = array(); // array('<room_id>' => <room DB row array>);
	var $locations = array(); // array('<location_id>' => <location DB row array>);

	var $errors = array(); // submission errors
	var $booking_date = ''; // passed from form/URL or defaults to current date
	var $booking_display_date = ''; // converted from booking date
	var $meeting_name = '';
	var $start_time = '';
	var $duration_minutes = '';
	var $room_id = '';
	var $location_id = '';

	// for calendar
	var $sql = '';
	var $booking_script_url = '';
	var $booking_submit_url = '';
	var $meeting_room_url = '';
	var $do_show_rooms_list = false;

	var $action = '';

    // ----------------------------------------
    //  Constructor
    // ----------------------------------------

    function Ncb_rooms()
    {
		$this->initialise_parameters();
		$this->initialise_module_settings();
		$this->initialise_submission();
		$this->initialise_database_info();
    }
    // END


	/**
	 * Load stored module settings (altered in the control panel))
	 */
	function initialise_module_settings()
	{
		global $DB;

		$sql = "SELECT * FROM exp_ncb_rooms_settings";
		$query = $DB->query($sql);

		foreach ($query->row as $field => $value)
		{
			$this->settings[$field] = $value;
		}

//		print_r($this->settings);

	} // end initialise_module_settings

	/**
	 * Grab any db table info needed to make/show bookings
	 */
	function initialise_database_info()
	{
		global $DB;

		$location_part = (empty($this->location_id) ? "" : " WHERE location_id = '$this->location_id'");

		$sql = "SELECT *
					FROM
						exp_ncb_rooms
					LEFT JOIN
						exp_ncb_room_locations ON location_idFK = location_id
					$location_part
					ORDER BY
						sort_order, exp_ncb_rooms.room_id
				";

		$query = $DB->query($sql);

		foreach ($query->result as $row)
		{
			$id = $row['room_id'];
			$this->rooms[$id] = $row;
		}
/*
		if (empty($this->room_id))
		{
			$ids = array_keys($this->rooms);
			$this->room_id = $ids[0];
			print("room id: $this->room_id");//TMP
		}		
*/		
//		print_r($this->rooms);

		$sql = "SELECT *
					FROM
						exp_ncb_room_locations
					ORDER BY
						location_id
				";

		$query = $DB->query($sql);

		foreach ($query->result as $row)
		{
			$id = $row['location_id'];
			$this->locations[$id] = $row;
		}

	} // end initialise_database_info

	/**
	 * Initialise variables from form or URL submission
	 */
	function initialise_submission()
	{
		$this->referer = $_POST['referer'];

		if (isset($_REQUEST['action']))
		{
			$this->action = $_REQUEST['action'];
		}

		$this->booking_date = $_REQUEST['booking_date'];
		$this->booking_id = $_REQUEST['booking_id'];

		$this->room_id = $_REQUEST['room_id'];

		$this->meeting_name = stripslashes($_POST['meeting_name']);
		$this->start_time = $_POST['start_time_hours'] . ":" . $_POST['start_time_minutes'];
		$this->duration_minutes = $_POST['duration_minutes'];

		if (isset($_REQUEST['start_time']))
		{
			$unix_start_time = $_REQUEST['start_time'];
			$this->start_time = date ("H:i", $unix_start_time);
		}

//		print_r($_REQUEST);//TMP

		if (empty($this->booking_date))
		{
			$this->booking_date = date ("Y-m-d", time());
		}

		if (!preg_match("/^\d\d\d\d-\d\d-\d\d$/", $this->booking_date))
		{
			$this->errors[] = "The requested booking date ($this->booking_date) was formatted incorrectly. ".
							  "Please ensure it is in the form: YYYY-MM-DD";
		}

		$date = $this->get_current_view_date();
		$unix_time = mktime (0, 0, 0, $date['m'], $date['d'], $date['y']);
		$today = mktime(0, 0, 0, date('n'), date('d'), date('Y'));
		$tomoz = mktime(0, 0, 0, date('n'), date('d')+1, date('Y'));
		if($unix_time == $today)
		{
			$this->booking_display_date = 'Today ('.date("l jS F Y", $unix_time).')';
		}
		else if($unix_time == $tomoz)
		{
			$this->booking_display_date = 'Tomorrow ('.date("l jS F Y", $unix_time).')';
		}
		else
		{
			$this->booking_display_date = date ("l jS F Y", $unix_time);
		}

		if (isset($_REQUEST['location_id']))
		{
			$this->location_id = $_REQUEST['location_id'];
		}
		
//		print("action: ".$this->action."<br/>");//TMP
		
	} // end initialise_submission

	/**
	 * Initialise any tag parameters passed from the EE template
	 **/
	function initialise_parameters()
	{
		global $TMPL;

		if (!empty($TMPL))
		{
			// get the action from the tags if not set in the form or URL parameters
			if (empty($this->action))
			{
				$this->action = $TMPL->fetch_param('action');
			}

	//		print("action: $this->action<br/>");//TMP

			// URL to the booking form and handler
			$this->booking_submit_url = $TMPL->fetch_param('booking_submit_url');
			$this->booking_script_url = $TMPL->fetch_param('booking_script_url');
			$this->meeting_room_url = $TMPL->fetch_param('meeting_room_url');

			// whether to show rooms list
			$this->do_show_rooms_list = eregi("yes|true|1", $TMPL->fetch_param('show_rooms_list'));

			// use current page if none is specified in the parameters
			$this->booking_script_url = (empty($this->booking_script_url) ? $_SERVER['PHP_SELF'] : $this->booking_script_url);
			$this->booking_submit_url = (empty($this->booking_submit_url) ? $_SERVER['PHP_SELF'] : $this->booking_submit_url);
			$this->meeting_room_url = (empty($this->meeting_room_url) ? $_SERVER['PHP_SELF'] : $this->meeting_room_url);

			if (empty($this->location_id))
			{
				$this->location_id = $TMPL->fetch_param('location_id');
			}
		}
	} // end initialise_parameters


	/**
	 * Handle booking submissions, output success/failure messages & booking form
	 */
	function booking_form()
	{
		global $SESS;

		if (isset($_POST['submit_ok']))
		{
			$this->return_data = $this->handle_booking();
		}
		else if ((isset($_POST['submit_cancel'])))
		{
			$this->return_data = "<p>You have chosen to cancel room booking</p>";

			if (!empty($this->referer))
			{
				$this->return_data .= "<a title=\"back to previous page\" href=\"$this->referer\">back</a>";
			}
		}
		else
		{
			$member_id = $SESS->userdata['member_id'];

			if (empty($member_id))
			{
				$this->errors[] = "You must be logged in to make a booking.";
			 	$this->return_data = $this->get_errors_html();// . "referer: $this->referer";

				$referer = (empty($this->referer) ? $_SERVER['HTTP_REFERER'] : $_POST['referer']);

				if (!empty($referer))
				{
					$this->return_data .= "<a title=\"back to previous page\" href=\"$referer\">back</a>";
				}
			}
			else
			{
				$this->return_data = $this->output_booking_form();
			}
		}

		// clear unused EE tags
		$this->return_data = preg_replace("/\{[^}]*\}/", "", $this->return_data);

		return $this->return_data;

	} // end booking_form



	/**
	 * Validate submitted booking information and either return errors (in $this->errors)
	 * or make the database entry for the booking
	 **/
	function handle_booking()
	{
		global $DB, $SESS;

		// check if attempting to make booking in the past
		$is_booking_time_past = $this->is_requested_booking_time_past();

		$is_booking_in_current_slot = $this->is_booking_in_current_slot();

		$is_within_booking_day = $this->is_requested_meeting_within_booking_day();

		$is_before_max = $this->is_requested_booking_time_before_maximum();
		
		if ($is_booking_time_past && !$is_booking_in_current_slot) // output error and show booking form
		{
			$this->errors[] = "You cannot make a booking in the past.";
			$tag_data = $this->output_booking_form();
		}
		else if (!$is_before_max) 
		{
			$max_advance_booking_days = $this->settings['max_advance_booking_days'];			
			$this->errors[] = "You cannot make a booking more than $max_advance_booking_days days in advance.";
			$tag_data = $this->output_booking_form();		         
		}
		else if (!$is_within_booking_day) // output error and show booking form
		{
			$this->errors[] = "Your booking must start and finish on the same day.";
			$tag_data = $this->output_booking_form();
		}
		else if (strlen($this->meeting_name) > 0) // go ahead and make the booking
		{
			$start_time = "$this->booking_date "."$this->start_time" . ":00";

			$member_id = $SESS->userdata['member_id'];

			if ($member_id > 0)
			{
				$sql = "SELECT DATE_ADD('$start_time', INTERVAL $this->duration_minutes MINUTE) AS end_time";
				$query = $DB->query($sql);
				$end_time = $query->row['end_time'];

				// see if the time clashes for this room
				$sql = "SELECT
							exp_ncb_room_bookings.*,
							UNIX_TIMESTAMP(start_time) as unix_start,
							UNIX_TIMESTAMP(end_time) as unix_end,
							exp_ncb_rooms.*,
							exp_members.screen_name, exp_members.username, exp_members.email
						FROM
							exp_ncb_room_bookings, exp_ncb_rooms, exp_members
						WHERE
							room_idFK = '$this->room_id' AND
							(
							 ('$start_time' >= start_time AND '$start_time' < end_time) OR
							 ('$start_time' <= start_time AND '$end_time' > start_time)
							)
							AND
							room_idFK = room_id AND
							user_idFK = member_id
						";

//				$tag_data = "<hr/>$sql<hr/>";//TMP

				$query = $DB->query($sql);

	            if ($query->num_rows > 0)
	            {
					foreach($query->result as $row)
					{
//						print_r($row);//TMP
//						print("clashes: {$row['activity_name']}<br/>");//TMP
						$meeting_name = stripslashes($row['activity_name']);
						$room_name = $this->rooms[$this->room_id]['room_name'];
						$start =  date ("H:i", $row['unix_start']);
						$end = date ("H:i", $row['unix_end']);

						$screen_name = $row['screen_name'];
						$username = $row['username'];
						$owner = (empty($screen_name) ? $username : $screen_name);
						$email = $row['email'];

						if (!empty($email))
							$owner = "<a title=\"Send email to booking owner\" href=\"mailto:$owner <$email>?subject=Your room booking for $this->booking_display_date ($start - $end) in '$room_name'\">$owner</a>";

						$this->errors[] = "Your booking clashes with another meeting in $room_name:<br />($start - $end) \"$meeting_name\" "
										  ."(booked by $owner).";
					}

					$tag_data = $this->output_booking_form();
				}
				else // time doesn't clash, so make the booking
				{
					$insert_id = $this->add_booking($this->room_id, $member_id, $start_time, $end_time, $this->meeting_name);

		            if ($insert_id > -1)
		            {
						$tag_data = "<p>Thank you, your booking was successful.</p>";

						if (!empty($this->referer))
						{
							$tag_data .= "<a title=\"back to previous page\" href=\"$this->referer\">back</a>";
						}
					}
					else
					{
						$this->errors[] = "There was a problem making the booking.";
						$tag_data = $this->output_booking_form();
					}
				}

//				$tag_data .= "<hr/>$sql<hr/>";//TMP
	//		 	print("booking made<br />");//TMP
			}
			else
			{
				$this->errors[] = "You must be logged in to book a meeting room.";
				$tag_data = $this->output_booking_form();
			}
		}
		else
		{
			$this->errors[] = "You must specifiy a meeting name.";
			$tag_data = $this->output_booking_form();
		}

		return $tag_data;

	} // end handle_booking


	function add_booking($room_id, $member_id, $start_time, $end_time, $meeting_name)
	{
		global $DB;

		$sql = "INSERT INTO exp_ncb_room_bookings SET
						room_idFK = '$room_id',
						user_idFK = '$member_id',
						start_time = '$start_time',
						end_time = '$end_time',
						activity_name = '".mysql_escape_string($meeting_name)."' ";

		$query = $DB->query($sql);

		if (mysql_affected_rows() > 0) {
			return $DB->insert_id;
		}

		return -1;
	}


	/**
	 * check if attempting to make booking in the past
	 * @return whether the current booking date and time is in the past
	 **/
	function is_requested_booking_time_past($unix_booking_time='')
	{
		$is_past = FALSE;

		$unix_now = time();

		if (empty($unix_booking_time))
		{
			$unix_booking_time = $this->get_booking_as_unixtime($this->booking_date, $this->start_time);
		}

		$is_past = ($unix_booking_time < $unix_now);

//		print("is_requested_booking_time_past() $unix_booking_time (".date('d/m H:i', $unix_booking_time).") < $unix_now ? ".($is_past ? 'YES' : 'no')."<br/>");//TMP

		return $is_past;

	} // end is_requested_booking_time_past


	/**
	 * check if attempting to make booking after the max advance booking date
	 * @return whether the current booking date and time is before max booking date
	 **/
	function is_requested_booking_time_before_maximum($unix_booking_time="")
	{
		if ($this->is_admin())
		{
			return TRUE;
		}
		if ($this->is_hr())
		{
			return TRUE;
		}
		$is_before = FALSE;
	
		if (empty($unix_booking_time))
		{
			$unix_booking_time = $this->get_booking_as_unixtime($this->booking_date, $this->start_time);
		}

		$unix_now = time();
		$d = date ("d", $unix_now);
		$m = date ("m", $unix_now);
		$y = date ("Y", $unix_now);

		$max_advance_booking_days = $this->settings['max_advance_booking_days'];

		$max_booking_time = mktime (0, 0, 0, $m, $d + $max_advance_booking_days + 1, $y);
		
		$is_before = ($unix_booking_time < $max_booking_time);
		
		return $is_before;
		
	} // end is_requested_booking_time_before_maximum
	
	
	/**
	 * @return The start and end timestamp of the current booking slot e.g.
	 * array(<start timestamp> => <end timestamp>)
	 **/
	function get_current_slot_times()
	{
		$slot_info = array();

		$unix_now = time();
		$d = date("d", $unix_now);
		$m = date("m", $unix_now);
		$y = date("Y", $unix_now);

		$slot_times = $this->get_slot_times($d, $m, $y);

		foreach ($slot_times as $unix_start => $unix_end)
		{
			if ($unix_now >= $unix_start && $unix_now < $unix_end)
			{
			 	$slot_info[$unix_start] = $unix_end;
				break;
			}
		}

		return $slot_info;

	} // end get_current_slot_times


	/**
	 * check if booking time is within the current time slot
	 * @return whether the booking date and time is in the current slot
	 **/
	function is_booking_in_current_slot($unix_booking_time='')
	{
		$is_in_slot = FALSE;

		if (empty($unix_booking_time))
		{
			$unix_booking_time = $this->get_booking_as_unixtime($this->booking_date, $this->start_time);
		}

		$slot_times = $this->get_current_slot_times();
		$keys = array_keys($slot_times);
		$unix_start = $keys[0];
		$unix_end = $slot_times[$unix_start];

		$is_in_slot = ($unix_booking_time >= $unix_start && $unix_booking_time < $unix_end);

//		print("is_booking_in_current_slot() $unix_booking_time (".date('d/m H:i', $unix_booking_time).") [$unix_start - $unix_end] ? ".($is_in_slot ? 'YES' : 'no')."<br/>");//TMP

		return $is_in_slot;

	} // end is_booking_in_current_slot

	/**
	 * @param $booking_date Y-m-d
	 * @param $start_time HH:MM
	 * @return The unix timestamp equivalent for the specifed date and tim
	 **/
	function get_booking_as_unixtime($booking_date, $start_time)
	{
		$date_parts = explode("-", $booking_date);
		list($y, $m, $d) = $date_parts;
		$time_parts = explode(":", $start_time);
		list($hour, $min) = $time_parts;

		if (empty($hour) || empty($min))
		{
			$hour = "23";
			$min = "59";
		}
//		print("hour: $hour min: $min<br/>");//TMP
		$unix_booking_time = mktime ($hour, $min, 59, $m, $d, $y);

		return $unix_booking_time;

	} //get_booking_as_unixtime


	/**
	 *
	 * @return Whether the requested booking start time fall within the
	 * bookable hours of the current booking date.
	 *
	 **/
	function is_requested_meeting_within_booking_day()
	{
		$is_within_day = FALSE;

		$date_parts = explode("-", $this->booking_date);
		list($y, $m, $d) = $date_parts;
		$time_parts = explode(":", $this->start_time);
		list($hour, $min) = $time_parts;

//		print("hour: $hour min: $min<br/>");//TMP
		$unix_booking_start = mktime ($hour, $min, 0, $m, $d, $y);
		$unix_booking_end = mktime($hour, $min + $this->duration_minutes, - 1, $m, $d, $y);
		$end_day = date ("d", $unix_booking_end);
		$end_hour = date ("H", $unix_booking_end);

//		$end_time = date("H:i", $unix_booking_end);//TMP
//		print("end time: $end_time end hour: $end_hour latest booking slot: $this->latest_slot_hour<br/>");//TMP

		$is_within_day = ($d == $end_day &&
						  $end_hour < $this->latest_slot_hour &&
						  $hour >= $this->earliest_slot_hour);

		return $is_within_day;

	} // is_requested_meeting_within_booking_day


	/**
	 * Process the template HTML and return the output
	 * @return Template HTML with booking form tags replaced
	 **/
	function output_booking_form($tag_content='')
	{
		global $TMPL, $DB, $IN, $FNS, $SESS;

//		$current_dir = dirname($_SERVER['PHP_SELF']);//TMP
//		print("current dir: $current_dir<br/>");//TMP

//		ob_start();//TMP
//		print_r($TMPL);//TMP
//		$output = htmlspecialchars(ob_get_contents());//TMP
//		ob_end_clean();//TMp
//		print("<hr>$output</hr>");//TMP

		$tag_data = (empty($tag_content) ? $TMPL->tagdata : $tag_content);
		$tag_data = html_entity_decode($tag_data);
//		print("<br />tag data: ".htmlspecialchars($tag_data));//TMP

		$tag_data = $this->output_errors($tag_data); // output any errors

		$form_fields = array();

		// meeting name textfield
		preg_match("/\{field_meeting_name([^}]*)\}/i", $tag_data, $matches);
		$attributes = trim($matches[1]);
		$attributes = (strlen($attributes) > 0 ? $attributes : "size=\"50\" maxlen=\"200\"");
		$meeting_name_html = "\n<input type=\"text\" name=\"meeting_name\" $attributes value=\"$this->meeting_name\" />\n";
		$form_fields['meeting_name'] = $meeting_name_html;


		// start-time hours drop-down
		$time_parts = explode(":", $this->start_time);
		$current_start_hour = $time_parts[0];
		$current_start_minute = $time_parts[1];
//		print("<hr/>time parts: $current_start_hour : $current_start_minute<hr/>");//TMP

		$hour_options = '';
		for ($i = $this->earliest_slot_hour; $i < $this->latest_slot_hour; $i++)
		{
			$label = strval($i);

			if (strlen($label) == 1)
				$label = "0" . $label;

			$selected = ($label == $current_start_hour ? 'selected' : '');
			$hour_options .= "\n<option value=\"$label\" $selected >$label</option>\n";
		}

		preg_match("/\{field_start_time_hours([^}]*)\}/i", $tag_data, $matches);
		$attributes = trim($matches[1]);
		$start_time_hours_html = "\n<select name=\"start_time_hours\" $attributes >\n$hour_options\n</select>\n";
		$form_fields['start_time_hours'] = $start_time_hours_html;


		// start-time minutes drop-down	- only output values matching current granularity
		$booking_granularity = $this->settings['booking_granularity'];
		$minutes_options = '';

		for ($i = 0; $i < 60; $i++)
		{
			$label = strval($i);

			if (strlen($label) == 1)
				$label = "0" . $label;

			$selected = ($label == $current_start_minute ? 'selected' : '');

			if ($i % $booking_granularity == 0)
			{
				$minutes_options .= "\n<option value=\"$label\" $selected >$label</option>\n";
			}
		}

		preg_match("/\{field_start_time_minutes([^}]*)\}/i", $tag_data, $matches);
		$attributes = trim($matches[1]);
		$start_time_minutes_html = "\n<select name=\"start_time_minutes\" $attributes >\n$minutes_options\n</select>\n";
		$form_fields['start_time_minutes'] = $start_time_minutes_html;

		// meeting duration drop-down
		$number_of_hours = ($this->latest_slot_hour - $this->earliest_slot_hour);
		$max_duration = $number_of_hours * 60;

		$minutes_options = '';
		for ($i = $booking_granularity; $i <= $max_duration; $i += $booking_granularity)
		{
			$hours = floor($i / 60);
			$mins = ($i % 60);

			$plural = ($hours == 1 ? '' : 's');
			$label = ($hours > 0 ? "$hours hour".$plural." $mins minutes" : "$i minutes");
			$label = ($mins == 0 ? "$hours hour".$plural : $label);

			$selected = ($i == $this->duration_minutes ? 'selected' : '');
			$minutes_options .= "\n<option value=\"$i\" $selected >$label</option>\n";
		}

		preg_match("/\{field_duration_minutes([^}]*)\}/i", $tag_data, $matches);
		$attributes = trim($matches[1]);
		$duration_minutes_html = "\n<select name=\"duration_minutes\" $attributes >\n$minutes_options\n</select>\n";
		$form_fields['duration_minutes'] = $duration_minutes_html;

		// meeting date
		$max_advance_booking_days = $this->settings['max_advance_booking_days'];

		$date = $this->booking_date;
		$date_field_html = "\n<input type=\"hidden\" name=\"booking_date\" value=\"$date\" />\n";

		// rooms drop-down

		$room_options = '';
		foreach ($this->rooms as $room_id => $row)
		{
			$name = $row['room_name'];
			$location = $row['location_name'];
			$selected = ($room_id == $this->room_id ? 'selected' : '');
			$room_options .= "\n<option value=\"$room_id\" $selected >$name - $location</option>\n";
		}

		preg_match("/\{field_room([^}]*)\}/i", $tag_data, $matches);
		$attributes = trim($matches[1]);

		$base_url = $_SERVER['PHP_SELF'] . "?booking_date=$this->booking_date&amp;action=$this->action";
		$on_change_url = $base_url . "&amp;room_id=";
		$on_change_script = "document.location = '$on_change_url' + this.options[this.selectedIndex].value";

//		if (empty($this->room_id)) // output select form element
//		{
			$room_html = "\n<select onChange = \"$on_change_script\" name=\"room_id\" $attributes >\n$room_options\n</select>\n";
//		}
//		else // output hidden field
//		{
//			$name = $this->rooms[$this->room_id]['room_name'];
//			$room_html = "\n<input type=\"hidden\" name=\"room_id\" value=\"$this->room_id\" />$name\n";
//		}

		$form_fields['room'] = $room_html;


		// submit buttons
		preg_match("/\{field_submit_ok([^}]*)\}/i", $tag_data, $matches);
		$attributes = trim($matches[1]);
		$attributes = (strlen($attributes) > 0 ? $attributes : "value=\"Book room\"");
		$submit_ok_html = "\n<input type=\"submit\" name=\"submit_ok\" $attributes />\n";
		$form_fields['submit_ok'] = $submit_ok_html;

		preg_match("/\{field_submit_cancel([^}]*)\}/i", $tag_data, $matches);
		$attributes = trim($matches[1]);
		$attributes = (strlen($attributes) > 0 ? $attributes : "value=\"Cancel\"");
		$submit_cancel_html = "\n<input type=\"submit\" name=\"submit_cancel\" $attributes />\n";
		$form_fields['submit_cancel'] = $submit_cancel_html;

//		print_r($form_fields);//TMP

		// replace all of the EE tags with the form field html
		foreach ($form_fields as $name => $html)
		{
			$regex = "\{field_".$name."[^}]*\}";
			$tag_data = preg_replace("/$regex/i", $html, $tag_data);
		}

		$referer = (empty($this->referer) ? $_SERVER['HTTP_REFERER'] : $this->referer);
		$referer_field_html = "<input type=\"hidden\" name=\"referer\" value=\"$referer\" />";

		$self = $_SERVER['PHP_SELF'];
		$tag_data =
<<<END_HTML
			<form name="booking_form" method="post" action="$this->booking_submit_url">
				$tag_data
				$date_field_html
				$referer_field_html
			</form>
END_HTML;


		// other booking info

		$tag_data = str_replace("{booking_date}", $this->booking_display_date, $tag_data);

		$member_id = $SESS->userdata['member_id'];
		$username = $SESS->userdata['username'];
		$screen_name = $SESS->userdata['screen_name'];
		$owner = (empty($screen_name) ? $username : $screen_name);
//		$owner .= " ($member_id)";

		$tag_data = str_replace("{booking_owner}", $owner, $tag_data);

		return $tag_data;

	} // end output_booking_form

	/**
	 * Replace error tags with error message HTML
	 * @return processed template HTML
	 **/
	function output_errors($tag_data="")
	{
		global $TMPL;

		$tag_data = ($tag_data == "" ? $TMPL->tagdata : $tag_data);

		$output_html = $this->get_errors_html();

		$tag_data = str_replace("{errors}", $output_html, $tag_data);

		return $tag_data;

	} // end output_errors

	/**
	 * @return Formatted HTML with error messages
	 **/
	function get_errors_html()
	{
		$output_html = '';

		if (sizeof($this->errors) > 0)
		{
			$output_html = "\n<ul>\n";

			foreach ($this->errors as $message)
			{
				$output_html .= "<li>$message</li>\n";
			}

			$output_html .= "</ul>\n";
		}

		return $output_html;

	} // end get_errors_html


	// ############ CALENDAR FUNCTIONS ##############

    // ----------------------------------------
    //  Meeting rooms Calendar
    // ----------------------------------------
	/**
	 * Output the various views of the meeting room calendar
	 */
    function calendar()
	{
//		print("action: $this->action<br/>");//TMP

		global $TMPL;
		$tag_data = $TMPL->tagdata;

		switch($this->action)
		{
			case 'day_view':
				$tag_data = $this->strip_tags($tag_data, array('rooms_view'));
				$this->return_data = $this->output_daily_view($tag_data);
				break;
			/*case 'week_view':
				$tag_data = $this->strip_tags($tag_data, array('rooms_view'));
				$this->return_data = $this->output_weekly_view($tag_data);
				break;*/
			case 'rooms_view':
				$this->return_data = $this->output_rooms_view();
				break;
			case 'cancel_booking':
				$this->return_data = $this->cancel_booking();
				$this->do_show_rooms_list = false;
				break;
			/*case 'calendar_view':
				$tag_data = $this->strip_tags($tag_data, array('rooms_view'));
				$this->return_data = $this->output_calendar_view($tag_data);
//				$this->do_show_rooms_list = false;
				break;*/
			case 'quick_links':
				$this->return_data = $this->output_quick_links();
//				$this->do_show_rooms_list = false;
				break;
			case 'end_booking':
				$this->return_data = $this->end_booking();
				break;
			default :
				$this->return_data = $this->strip_tags($tag_data, array('rooms_view'));
		} // switch

		if ($this->do_show_rooms_list)
		{
			$this->return_data = $this->output_rooms_list($this->return_data);
		}

		if (!empty($this->room_id))
		{
			$room_name = $this->rooms[$this->room_id]['room_name'];
			$this->return_data = str_replace("{room_name}", $room_name, $this->return_data);
		}

		// do any string limiting requried e.g. {char_limit limit="10"}some text to shorten{/char_limit}
		//
		$regex = "\{char_limit +limit *= *\"(.+)\"[^}]*\}(.+)\{(/|&#47;)char_limit\}";
		$this->return_data = preg_replace_callback("'$regex'siU",
								create_function(
									'$matches',
									'
										$len = strlen($matches[2]);
										$result = substr($matches[2], 0, $matches[1]);
										$result .= ($len > $matches[1] ? "..." : "");
										return $result;
									'
								),
								$this->return_data
							 );
		// clear up unused EE tags and their contents
		$regex = "\{([^}]*)\}(.*\{(/|&#47;)\\1\})?";
		$this->return_data = preg_replace("'$regex's", "", $this->return_data);
		//$this->return_data = preg_replace("/\{[^}]*\}/", "", $this->return_data);

//		print("<hr/><div style=\"background-color: #FFF;\">".htmlspecialchars($this->return_data)."</div><hr/>");//TMP

		return $this->return_data;

    } // calendar

	/**
	 * Remove specified tags and their contents
	 */
	function strip_tags($content, $tag_names)
	{
//		print("strip_tags()<br/>");//TMP
//		print("<hr/><div style=\"background-color: #FFF;\">".htmlspecialchars($content)."</div><hr/>");//TMP

		foreach ($tag_names as $tag)
		{
			$regex = "\{".$tag."( [^}])*\}.*\{(/|&#47;)".$tag."\}";
			$content = preg_replace("'$regex's", "", $content);
		}

//		print("<hr/><div style=\"background-color: #FFF;\">".htmlspecialchars($content)."</div><hr/>");//TMP

		return $content;

	} // end strip_tags

	/**
	 * Deletes a booking from the bookings table
	 * @todo: check that the currently logged in person is allowed to cancel
	 **/
	function cancel_booking()
	{
		global $TMPL, $DB;

		$tag_data = $TMPL->tagdata;

		$message = '';

		if ($this->booking_id > 0)
		{
			$sql = "DELETE FROM exp_ncb_room_bookings WHERE room_booking_id = $this->booking_id";

			$query = $DB->query($sql);

            if (mysql_affected_rows() > 0)
            {
				$message = "Thank you, this booking has been cancelled.";
			}
			else
			{
				$message = "There was a problem cancelling the booking.";
			}
		}
		else
		{
			$message = "No booking id was provided";
		}

	 	$this->referer .= "?booking_date=$this->booking_date&amp;room_id=$this->room_id";

		$output = $this->output_message($tag_data, $message);

		return $output;

	} // end cancel_booking
	/**
	 * Ends a booking in the bookings table
	 * @todo: check that the currently logged in person is allowed to cancel
	 **/
	function end_booking()
	{
		global $TMPL, $DB;

		$tag_data = $TMPL->tagdata;

		$message = '';

		if (($this->booking_id > 0))
		{
			//Get the current booking details.
	 		$sql = "SELECT start_time,	end_time" .
	 				" FROM exp_ncb_room_bookings WHERE room_booking_id = '".$this->booking_id."' ";
	 		$query = $DB->query($sql);
	 		
	 		if($query->num_rows == 1)
	 		{
	 			$start_time = strtotime($query->row['start_time']);
	 			$end_time = strtotime($query->row['end_time']);
				
				//Get the current slot
				$current_slot = $this->get_current_slot_times();
				$keys = array_keys($current_slot);
				$unix_start = $keys[0];
				$unix_end = $current_slot[$unix_start];
	 			
				if(($start_time<=$unix_start)&&($end_time>=$unix_end))
				{
					$meeting_longer = $unix_start>$start_time; 
					$new_end = ($meeting_longer ? date("Y-m-d H:i:s", $unix_start) : date("Y-m-d H:i:s", $unix_end));
					$sql = "UPDATE exp_ncb_room_bookings SET".
							" end_time = '$new_end'".
							" WHERE room_booking_id = '".$this->booking_id."'";
							
					//print_r($sql);
					$query = $DB->query($sql);
		
		            if (mysql_affected_rows() > 0)
		            {
						$message = "Thank you, this booking has been shortened.";
					}
					else
					{
						$message = "There was a problem ending the booking.";
					}
				
				}
				else
				{
					$message = "This meeting is not currently happening - unable to shorten.";
				}
			}
			else
			{
				$message = "More than one booking with this id.";
			}
		}
		else
		{
			$message = "No booking id was provided";
		}

	 	$this->referer .= "?booking_date=$this->booking_date&amp;room_id=$this->room_id";

		$output = $this->output_message($tag_data, $message);

		return $output;

	} // end end_booking


	/**
	 *
	 * @access public
	 * @return void
	 **/
	function output_message($tag_content, $message_text)
	{
		preg_match("'\{messages[^}]*\}(.+)\{(/|&#47;)messages\}'siU", $tag_content, $matches);
		$messages_content = $matches[1];

		$this->referer = $_SERVER['HTTP_REFERER'];

		$messages_content = str_replace("{message}", $message_text, $messages_content);
		$messages_content = str_replace("{previous_url}", $this->referer, $messages_content);

		$output = preg_replace("'\{messages[^}]*\}(.+)\{(/|&#47;)messages\}'siU", $messages_content, $tag_content);

		return $output;
	}


	/**
	 * Get an array representing the current view date (or 1st day in week view)
	 * @return array('d' => <day>, 'm' => <month>, 'y' => <year>)
	 **/
	function get_current_view_date()
	{
		global $TMPL, $IN, $LOC;

		$year  = '';
		$month = '';
		$day = '';

		// Hard-coded month/year via tag parameters

		if (!empty($TMPL) AND $TMPL->fetch_param('month') AND $TMPL->fetch_param('year'))
		{
			$year 	= $TMPL->fetch_param('year');
			$month	= $TMPL->fetch_param('month');
			$day	= $TMPL->fetch_param('day');

			if (strlen($month) == 1)
				$month = '0'.$month;

			if (strlen($day) == 1)
				$day = '0'.$day;
		}
		else
		{
			// Month/year in query string

			if (preg_match("#(\d{4}/\d{2})#", $IN->QSTR, $match))
			{
				$ex = explode('/', $match['1']);

				$time = mktime(0, 0, 0, $ex['1'], 01, $ex['0']);
				// $time = $LOC->set_localized_time(mktime(0, 0, 0, $ex['1'], 01, $ex['0']));

				$year  = date("Y", $time);
				$month = date("m", $time);
				$day = date("d", $time);
			}
			else
			{
				// Defaults to current month/year

				$year  = date("Y", $LOC->set_localized_time($LOC->now));
				$month = date("m", $LOC->set_localized_time($LOC->now));
				$day = date("d", $LOC->set_localized_time($LOC->now));
			}
    	}

		if (isset($_REQUEST['booking_date'])) // get the viewing month from the current booking date
		{
			$parts = explode("-", $this->booking_date);
			$day = $parts[2];
			$month = $parts[1];
			$year = $parts[0];
		}

		$current_view_date = array('d' => $day, 'm' => $month, 'y' => $year);

		return $current_view_date;

	} // end get_current_view date


	/**
	 *
	 * Using the current booking granularity, generate a bunch of slot times
	 * for the daily/weekly view.
	 *
	 * Times start at earliest booking time and end at latest booking time.
	 *
	 * @param $day numeric day of the month
	 * @param $month numeric month
	 * @param $year current year
	 * @return an array of unix timestamp values representing slots i.e. array(unix_start => unix_end ...)
	 **/
	function get_slot_times($day, $month, $year)
	{
		$slot_times = array();
		$booking_granularity = $this->settings['booking_granularity'];
		$slot_length_seconds = (60 * $booking_granularity);

//		$unix_date = mktime ($e_hour, $e_mins, 0, $month, $day, $year); // current viewing day as a timestamp
//		$end_unix_date = mktime ($l_hour, $l_mins, 59, $month, $day, $year); // the end of the current viewing day

		/*
		for ($i = $unix_date; $i <= $end_unix_date; $i += $slot_length_seconds)
		{
			$slot_times[$i] = ($i + $slot_length_seconds);
		}
		*/

		$num_hours = ($this->latest_slot_hour - $this->earliest_slot_hour);

		$num_slots = ($num_hours * 60) / $booking_granularity;

		for ($i = 0; $i < $num_slots; $i++)
		{
			$start = mktime ($this->earliest_slot_hour, $i * $booking_granularity, 0, $month, $day, $year);
			$end = $start + $slot_length_seconds;
			$slot_times[$start] = $end;
		}

		return $slot_times;

	} // get_slot_times


	/**
	 *
	 * @param booking date for which to return rows (format YYYY-MM-DD)
	 * (defaults to current view date)
	 * @param room_id, to specify for a particular room (defaults to current room id)
	 * @return database rows for bookings on the specified date
	 * (rows keyed by booking start time for easy output into slots)
	 **/
	function get_booking_rows($booking_date='', $room_id='', $order_by="start_time ASC")
	{
		global $DB;

		$booking_rows = array();

		$booking_date = (empty($booking_date) ? $this->booking_date : $booking_date);
		$room_id = (empty($room_id) ? $this->room_id : $room_id);

		$room_id_clause = ($room_id > 0 ? "room_id = '$room_id' AND" : "");

		$sql = "SELECT
					exp_ncb_room_bookings.*,
					UNIX_TIMESTAMP(start_time) as unix_start,
					UNIX_TIMESTAMP(end_time) as unix_end,
					exp_ncb_rooms.*,
					exp_members.*,
					exp_member_groups.*
				FROM
					exp_ncb_room_bookings, exp_ncb_rooms, exp_members, exp_member_groups
				WHERE
					room_idFK = room_id AND
					$room_id_clause
					user_idFK = member_id AND
					exp_members.group_id = exp_member_groups.group_id AND
					(
					  (start_time >= '$booking_date 00:00:00'
					   AND
					   start_time <= '$booking_date 23:59:59')
					   OR
					  (end_time >= '$booking_date 00:00:00'
					   AND
					   end_time <= '$booking_date 23:59:59')
					)
				ORDER BY
					$order_by
				";

//		print("<hr/><div style=\"background-color: #FFF;\">".htmlspecialchars($sql)."</div><hr/>");//TMP

		$query = $DB->query($sql);

		if ($query->num_rows > 0)
		{
			foreach($query->result as $row)
			{
				$unix_start = $row['unix_start'];
				$booking_rows[$unix_start] = $row;
			}
		}

		return $booking_rows;

	} // end get_booking_rows


	/**
	 * @return The group primary key for the admin user group
	 **/
	function get_admin_group_id()
	{
		global $DB;

		$sql = "SELECT * FROM exp_member_groups WHERE group_title LIKE '%admin%'";
		$query = $DB->query($sql);
		$admin_group_id = $query->row['group_id'];

		return $admin_group_id;
	}

	/**
	 * @return whether the currently logged in user is an admin
	 **/
	function is_admin()
	{
		global $SESS;
		
		$logged_in_member_id = $SESS->userdata['member_id'];
		$logged_in_member_group = $SESS->userdata['group_id'];
		$admin_group_id = $this->get_admin_group_id();
		
		$is_admin = ($logged_in_member_group == $admin_group_id);
		
		return (boolean)$is_admin;
	}


	/**
	 * @param $member_id The member id of the user to check
	 * @return Whether the currently logged in user is in the HR team
	 **/
	function is_hr()
	{
		global $SESS;

		$logged_in_user_id = $SESS->userdata['member_id'];
		$is_hr = $this->is_human_resources_member($logged_in_user_id);

		return (boolean)$is_hr;
	} // end is_logged_in_user_hr_member
	
	/**
	 *
	 * @return Whether the specified user is in the HR team
	 **/
	function is_human_resources_member($member_id)
	{
		$is_hr = FALSE;
	
		$userdata = $this->get_member_data($member_id);
		$username = $userdata['username'];
		$hr_members = array('jbrown','nmitchell');			
		$is_hr = (array_search($username, $hr_members) !== FALSE);
		
		return (boolean)$is_hr;
		
	} // end is_human_resources_member

	/**
	 *
	 * @return The data row from the members tables for the specified member id
	 * (or rows for all members if not specified)
	 **/
	function get_member_data($member_id='')
	{
		global $DB;

		$data = array();

		if (empty($member_id)) 
		{
			$wherePart = "WHERE 1 = 1";    
		}
		else
		{
			$wherePart = "WHERE member_id = '$member_id'";    
		}
		
		$sql = "
  			     SELECT * FROM
				   exp_members
			        $wherePart
			  ";

		$query = $DB->query($sql);

		if ($query->num_rows > 0)
		{
			if (empty($member_id)) 
			{
				foreach ($query->result as $row)
				{
					$id = $row['member_id'];
					$data[$id] = $row;
				}				
			}
			else
			{
				$data = $query->result[0];    
			}			
		}

		return $data;

	} // end get_member_data
	
	/**
	 * Display a list of all the bookings for the current viewing date
	 * (provide links to cancel and book also)
	 * @access public
	 * @return the view html
	 **/
	function output_daily_view($tag_data='')
	{
//		print("<hr/><div style=\"background-color: #FFF;\">output_daily_view</div><hr/>");//TMP

//		print("date now: ".(date ("d-m-Y H:i:s", time()))."<br/>");//TMP

		global $TMPL, $DB, $SESS;

		$tag_data = ($tag_data == '' ? $TMPL->tagdata : $tag_data);

		preg_match("'\{day_view[^}]*\}(.+)\{(/|&#47;)day_view\}'siU", $tag_data, $matches);
		$view_html = $matches[1];

		$view_html = $this->output_locations_list($view_html);
		$view_html = $this->output_rooms_list($view_html);
		$view_html = $this->output_available_dates_list($view_html);

//		print("<hr/><div style=\"background-color: #FFF;\">".htmlspecialchars($tag_data)."</div><hr/>");//TMP

		$room_name = $this->rooms[$this->room_id]['room_name'];
		$hex_colour = $this->rooms[$this->room_id]['hex_colour'];
		$extension = $this->rooms[$this->room_id]['extension'];
		$room_description = $this->rooms[$this->room_id]['room_description'];
		$room_location = $this->rooms[$this->room_id]['location_name'];
		$self = $_SERVER['PHP_SELF'];

		$current_view_date = $this->get_current_view_date();
		$day = $current_view_date['d'];
		$month = $current_view_date['m'];
		$year = $current_view_date['y'];

		$unix_date = mktime (0, 0, 0, $month, $day, $year); // current viewing day as a timestamp
		$end_unix_date = mktime (23, 59, 59, $month, $day, $year); // the end of the current viewing day
		$day_seconds = (24 * 60 * 60);

		$max_advance_booking_days = $this->settings['max_advance_booking_days'];
		$today = time();
		$start_of_today = mktime (0, 0, 0, date ("m"), date ("d"), date ("Y"));
		$end_of_today = mktime (23, 23, 59, date ("m"), date ("d"), date ("Y"));
//		$last_booking_day = $today + ($max_advance_booking_days * $day_seconds);
		$last_booking_day = mktime (0, 0, 0, date ("m"), date ("d") + $max_advance_booking_days, date ("Y"));

//		$previous_unix_day = $unix_date - $day_seconds;
		$previous_unix_day = mktime (0, 0, 0, $month, $day - 1, $year);
		$previous_date = date ("Y-m-d", $previous_unix_day);
//		$previous_day_url = $self . "?action=day_view&amp;booking_date=$previous_date&amp;room_id=$this->room_id";

//		$next_unix_day = $unix_date + $day_seconds;
		$next_unix_day = mktime (0, 0, 0, $month, $day + 1, $year);
		$next_date = date ("Y-m-d", $next_unix_day);
//		$next_day_url = $self . "?action=day_view&amp;booking_date=$next_date&amp;room_id=$this->room_id";

		$previous_link_html = "";
		if ($previous_unix_day >= $start_of_today)
		{
			$previous_link_html = "<a href=\"$self?action=day_view&amp;booking_date=$previous_date&amp;room_id=$this->room_id\" \\1 >\\2</a>";
		}

		$next_link_html = "";
		if ($next_unix_day <= $last_booking_day) // if next day is passed the last advance booking date
		{
			$next_link_html = "<a href=\"$self?action=day_view&amp;booking_date=$next_date&amp;room_id=$this->room_id\" \\1 >\\2</a>";
		}

//		print("previous link html: ".htmlspecialchars($previous_link_html)."<br/>");//TMP
//		print("next link html: ".htmlspecialchars($next_link_html)."<br/>");//TMP
//		print("previous unix day: $previous_unix_day today: $start_of_today (a < b) ?: ".($previous_unix_day < $start_of_today)."<br/>");//TMP

		// put the appropriate URLs in
		$week_view_url = $self . "?booking_date=$this->booking_date&amp;room_id=$this->room_id&amp;action=week_view";
		$view_html = str_replace("{week_view_url}", $week_view_url, $view_html);

		$rooms_view_url = $self . "?booking_date=$this->booking_date&amp;action=rooms_view&amp;location_id=$this->location_id";
		$view_html = str_replace("{rooms_view_url}", $rooms_view_url, $view_html);

		$calendar_view_url = $self . "?room_id=$this->room_id&amp;action=calendar_view";
		$view_html = str_replace("{calendar_url}", $calendar_view_url, $view_html);
		$view_html = preg_replace("'{previous_day_link([^}]*)\}(.+)\{(/|&#47;)previous_day_link\}'si", $previous_link_html, $view_html);
		$view_html = preg_replace("'{next_day_link([^}]*)\}(.+)\{(/|&#47;)next_day_link\}'si", $next_link_html, $view_html);

		// #### deal with displaying the bookings ####

		$logged_in_member_id = $SESS->userdata['member_id'];

		// get all the bookings for the current viewing day and room id
		// (organised for easy output into slots - keyed by start time)
		$booking_rows = $this->get_booking_rows(); // array(unix_start  => unix_end, ...)

		// generate set of time slots to output
		$slot_times = $this->get_slot_times($day, $month, $year); // array(unix_start  => unix_end, ...)

//		print("<hr/><div style=\"background-color: #FFF;\">SLOT TIMES<br/>");//TMP
//		print_r($slot_times);//TMP
//		print("</div><hr/>");//TMP

		preg_match("'\{booking_slot[^}]*\}(.+)\{(/|&#47;)booking_slot\}'siU", $view_html, $matches);
		$booking_slot_content = $matches[1];

//		print("<div style=\"border: solid 1px; background-color: #FFF;\">booking_slot_content: ".htmlspecialchars($booking_slot_content)."</div>");//TMP

		$slots_output_html = '';
		$current_booking_row = array();
		$cancel_shown = false;
		$end_booking_shown = false;

		$bookings_started = array(); // keep track of which bookings have started

		// replace each of the slots
		$slots_index = 0;

//		print("<div style=\"z-Index: 100; top: 820px; background-color: #FFF; position: absolute;\">\n");//TMP

		foreach($slot_times as $slot_unix_start => $slot_unix_end)
		{
//			print("[$slot_unix_start] ");//TMP
		
			$is_booking_start = false;
			$is_booking_end = false;

			$slot_html = $booking_slot_content;

			// locate a meeting that started during this slot
			$row = $this->get_slot_booking($slot_unix_start, $booking_rows);
						
			if (!empty($row)) // a booking row for the slot was found
			{
				$current_booking_row = $row;
				$cancel_shown = false;
				$end_booking_shown = false;
			}

			$is_slot_booked = (sizeof($current_booking_row) > 0);

			$booking_id = '';
			$booking_time ='';
			$meeting_name = '';
			$owner = '';
			$booking_url = '';

			$is_past = $this->is_requested_booking_time_past($slot_unix_start); // link to nothing if time has past
			$is_in_slot = $this->is_booking_in_current_slot($slot_unix_start);

			// slot NOT booked, so replace {if not_slot_booked) conditional tag content
			if (empty($current_booking_row))
			{
				if (empty($SESS->userdata['member_id']))
				{
					$booking_url = "javascript:alert('You must be logged in to make a booking')";
				}
				else
				{
					$booking_url = ($is_past && !$is_in_slot ?  "javascript:alert('You cannot make a booking in the past')" :
																$self . "?booking_date=$this->booking_date&amp;room_id=$this->room_id&amp;start_time=$slot_unix_start#booking_form");
				}
			}
			// slot IS booked, so replace {if slot_booked) conditional tag content
			else
			{
				$unix_start = $current_booking_row['unix_start'];
				$is_booking_start = !array_key_exists($unix_start, $bookings_started);
				$bookings_started[$unix_start] = $current_booking_row;

				$unix_end = $current_booking_row['unix_end'];
				$is_booking_end = ($unix_end == $slot_unix_end); // booking ends in this slot

				$booking_duration = ($unix_end - $unix_start);
				$slot_duration = ($slot_unix_end - $slot_unix_start);
				$slot_count = ceil($booking_duration / $slot_duration);

				$booking_id = $current_booking_row['room_booking_id'];
				$meeting_name = stripslashes($current_booking_row['activity_name']);
			 	$room_name = $current_booking_row['room_name'];
			 	$hex_colour = $current_booking_row['hex_colour'];
			 	$extension = $current_booking_row['extension'];
	//				print("room name: $room_name<br/>");//TMP
				$start =  date ("H:i", $unix_start);
				$end = date ("H:i", $unix_end);
				$booking_time = "$start - $end";

				$screen_name = $current_booking_row['screen_name'];
				$username = $current_booking_row['username'];
				$owner = (empty($screen_name) ? $username : $screen_name);
			    $owner_mailto = "";
				$email = $current_booking_row['email'];

				if (!empty($email))
					$owner_mailto = "<a title=\"Send email to booking owner\" href=\"mailto:$owner <$email>?subject=Your room booking for $this->booking_display_date ($start - $end) in '$room_name'\">$owner</a>";

				// only allow cancel if logged in as admin, if you own the booking and if it is in the future
				$is_cancel_allowed = (($this->is_admin() || $row['user_idFK'] == $logged_in_member_id) &&
									  $unix_end >= $today);
//				print("meeting: $meeting_name owner: $owner time: $booking_time is cancel allowed (by $logged_in_member_id)? : ".($is_cancel_allowed ? 'YES' : 'nope')."");//TMP

				$cancel_link_html = "";
				if ($is_cancel_allowed) // use the link text and extras from the {cancel_link} tag if allowed to show it
				{
					$cancel_link_html = "<a onclick=\"return confirm('Really cancel this booking?');\" href=\"$self?booking_date=$this->booking_date&amp;booking_id=$booking_id&amp;room_id=$this->room_id&amp;action=cancel_booking\" \\1 >\\2</a>";
				}

				$cancel_link_html = ($cancel_shown ? "" : $cancel_link_html);
//				print("<div style=\"border: solid 1px; background-color: #FFF;\">cancel allowed? [$is_cancel_allowed] cancel link html: ".htmlspecialchars($cancel_link_html)."</div>");//TMP
				$slot_html = preg_replace("'{cancel_link([^}]*)\}(.+)\{(/|&#47;)cancel_link\}'siU", $cancel_link_html, $slot_html);
				$cancel_shown = true;	

				// only allow end booking if logged in as admin, if you own the booking and it's not a single time-slot and the meeting is still in progress
				$is_in_progress = ($today >= $unix_start && $today <= $unix_end);
				$is_end_allowed = (($this->is_admin() || $row['user_idFK'] == $logged_in_member_id) &&
								  $is_in_progress && !($is_booking_start && $is_booking_end));

				$end_link_html = "";
				if ($is_end_allowed) // use the link text and extras from the {end_link} tag if allowed to show it
				{
					$end_link_html = "<a onclick=\"return confirm('Really end this booking now?');\" href=\"$self?booking_date=$this->booking_date&amp;booking_id=$booking_id&amp;room_id=$this->room_id&amp;action=end_booking\" \\1 >\\2</a>";
				}
				
				$end_link_html = ($end_booking_shown ? "" : $end_link_html);			
				$slot_html = preg_replace("'{end_link([^}]*)\}(.+)\{(/|&#47;)end_link\}'siU", $end_link_html, $slot_html);
				$end_booking_shown = true;	
			}

			$slot_start_time = date ("H:i", $slot_unix_start);
			$slot_end_time = date ("H:i", $slot_unix_end);
			$slot_time = "$slot_start_time - $slot_end_time";

//			print("<div style=\"border: solid 1px; background-color: #FFF;\">slot time: ".htmlspecialchars($slot_time)."</div>");//TMP

			// check if current slot
			$current_times = $this->get_current_slot_times();
			$keys = array_keys($current_times);
			$current_slot_start = $keys[0];
			$is_current_slot = ($slot_unix_start == $current_slot_start);
			$is_current_slot_replace = ($is_current_slot ? "\\1" : "");

//			print("[$slot_time] ($slot_unix_start - $slot_unix_end) current slot start: $current_slot_start is current ? ($is_current_slot)<br/>");//TMP
			$slot_html = preg_replace("'\{if current_slot[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_current_slot_replace, $slot_html);

			$slot_html = str_replace("{booking_script_url}", $booking_url, $slot_html);
			$slot_html = str_replace("{slot_time}", $slot_time, $slot_html);
			$slot_html = str_replace("{meeting_name}", $meeting_name, $slot_html);
			$slot_html = str_replace("{booking_owner}", $owner, $slot_html);
			$slot_html = str_replace("{booking_owner_email}", $email, $slot_html);
			$slot_html = str_replace("{booking_owner_mailto}", $owner_mailto, $slot_html);
			$slot_html = str_replace("{booking_time}", $booking_time, $slot_html);
			$slot_html = str_replace("{slot_count}", $slot_count, $slot_html);

//			print("<div style=\"border: solid 1px; background-color: #FFF;\">slot html: ".htmlspecialchars($slot_html)."</div>");//TMP

			// replace the conditionals
			$is_start_replace = "";
			$is_end_replace = "";
			$is_single_slot_replace = "";
			$is_mid_booking_replace = "";
			$is_not_mid_booking_replace = "";
			$is_next_slot_booked_replace = "";
			$is_past_replace = "";
			$is_not_past_replace = "";

			if ($is_slot_booked)
			{
				$is_not_mid_booking_replace = "\\1";

				if ($is_booking_start && $is_booking_end) // booking is a single-slot booking
				{
					$is_single_slot_replace = "\\1";
//					print("[$slot_time] $start - $end is single slot booking<br/>");//TMP
				}
				else
				{
					if ($is_booking_start)
					{
						$is_start_replace = "\\1";
//						print("[$slot_time] $start - $end is booking start<br/>");//TMP
					}
					else if ($is_booking_end)
					{
						$is_end_replace = "\\1";
//						print("[$slot_time] $start - $end is booking end<br/>");//TMP
					}
					else // current slot is in the middle of a booking somewhere
					{
						$is_mid_booking_replace = "\\1";
						$is_not_mid_booking_replace = "";
//						print("[$slot_time] $start - $end is mid-booking<br/>");//TMP
					}
				}

				$is_booked_replace = "\\1";
				$is_not_booked_replace = "";
			}
			else // slot not booked
			{
				$is_booked_replace = "";
				$is_not_booked_replace = "\\1";

				$is_past = ($is_past && !$is_in_slot);
				if ($is_past)
				{
					$is_past_replace = "\\1";
					$is_not_past_replace = "";
				}
				else
				{
					$is_past_replace = "";
					$is_not_past_replace = "\\1";
				}
//				print("[$slot_time] is not booked. past? ($is_past) is_past? ($is_past) is_in_slot? ($is_in_slot) ");//TMP
//				print("if past replacement: ($is_past_replace) if not_past replacement: ($is_not_past_replace)<br/>");//TMP
			}

			// check if next slot has a booking
			$temp_times = array_keys($slot_times);
			$next_slot_start = $temp_times[$slots_index + 1];
			$row = $this->get_slot_booking($next_slot_start, $booking_rows);
			if (!empty($row))
			{
				$is_next_slot_booked_replace = "\\1";
			}

			// do the replacements
			$slot_html = preg_replace("'\{if next_slot_booked[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_next_slot_booked_replace, $slot_html);
			$slot_html = preg_replace("'\{if booking_start[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_start_replace, $slot_html);
			$slot_html = preg_replace("'\{if booking_end[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_end_replace, $slot_html);
			$slot_html = preg_replace("'\{if single_slot[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_single_slot_replace, $slot_html);
			$slot_html = preg_replace("'\{if mid_booking[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_mid_booking_replace, $slot_html);
			$slot_html = preg_replace("'\{if not_mid_booking[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_not_mid_booking_replace, $slot_html);

//			print("<hr/><div style=\"background-color: #FFF;\">".htmlspecialchars($slot_html)."</div><hr/>");//TMP
			$slot_html = preg_replace("'\{if slot_in_past[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_past_replace, $slot_html);
			$slot_html = preg_replace("'\{if not_slot_in_past[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_not_past_replace, $slot_html);
//			print("<hr/><div style=\"background-color: #FFF;\">".htmlspecialchars($slot_html)."</div><hr/><br/><br/>");//TMP

			// these must come last because of nested conditionals
			$slot_html = preg_replace("'\{if slot_booked[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_booked_replace, $slot_html);
			$slot_html = preg_replace("'\{if not_slot_booked[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_not_booked_replace, $slot_html);


			// sort out css classes - from template {row_class options="option1|option2"}
			// use option1 if in a booked row, use option2 otherwise
			$option_replacement = ($is_slot_booked ? "\\1" : "\\2");
			$slot_html = preg_replace("'\{row_class +options *= *\"(.+)\|(.+)\" *\}'siU", $option_replacement, $slot_html);

			$slots_output_html .= "$slot_html\n";

			if ($is_booking_end)
			{
				$current_booking_row = null; // current booking ended in this slot
			}

			// see if the current booking ends during this slot
			if ($current_booking_row != null && sizeof($booking_rows) > 0)
			{
				$found = false;
				foreach ($booking_rows as $unix_start => $booking_row)
				{
					$unix_end = $booking_row['unix_end'];
					$found = ($unix_end < $slot_unix_end && $unix_end > $slot_unix_start);
					if ($found)
					{
						$current_booking_row = null;
						break;
					}
				}
			}

			$slots_index++;
//			print(" [".($cancel_shown ? 'cancel shown' : 'cancel NOT shown')."]<br/>\n");//TMP
		}
		
//		print("</div>\n");//TMP

//		print("<div style=\"border: solid 1px; background-color: #FFF;\">slot html: ".htmlspecialchars($slots_output_html)."</div>");//TMP
//		print("<div style=\"border: solid 1px; background-color: #FFF;\">room name: ".htmlspecialchars($room_name)."</div>");//TMP

		$view_html = str_replace("{booking_date}", $this->booking_display_date, $view_html);
		$view_html = str_replace("{booking_date_value}", $this->booking_date, $view_html);

		$view_html = str_replace("{room_id}", $this->room_id, $view_html);
		$view_html = str_replace("{room_name}", $room_name, $view_html);
		$view_html = str_replace("{hex_colour}", $hex_colour, $view_html);
		$view_html = str_replace("{extension}", $extension, $view_html);
		$view_html = str_replace("{room_description}", $room_description, $view_html);
		$view_html = str_replace("{room_location}", $room_location, $view_html);

		// replace the booking slot tag set with the combined set of booking entries
		$view_html = preg_replace("'\{booking_slot[^}]*\}(.+)\{(/|&#47;)booking_slot\}'si", $slots_output_html, $view_html);

		// output the booking entries in the place specified in the template
		$view_html = preg_replace("'\{bookings[^}]*\}(.+)\{(/|&#47;)bookings\}'si", "\\1", $view_html);

		// output the daily view in the place specified in the template
		$output = preg_replace("'\{day_view[^}]*\}(.+)\{(/|&#47;)day_view\}'si", $view_html, $tag_data);

		// output the booking form in the place specified in the template
		preg_match("'\{booking_form[^}]*\}(.+)\{(/|&#47;)booking_form\}'siU", $tag_data, $matches);
		$form_content = $matches[1];
		$this->referer = $_SERVER['PHP_SELF'] . "?booking_date=$this->booking_date&amp;room_id=$this->room_id"; // so that booking form returns to this view once submitted
		$form_html = $this->output_booking_form($form_content);

		$output = preg_replace("'\{booking_form[^}]*\}(.+)\{(/|&#47;)booking_form\}'si", $form_html, $output);

		return $output;

	} // end output_daily_view

	/**
	 * Find a booking within a particular slot
	 * @return A booking row corresponding to a booking within the specified time slot
	 */
	function get_slot_booking($slot_unix_start, $booking_rows)
	{
		$row = $booking_rows[$slot_unix_start];

		if (empty($row) && sizeof($booking_rows) > 0)
		{
			$found = false;
			foreach ($booking_rows as $unix_start => $booking_row)
			{
				$found = ($unix_start > $slot_unix_start && $unix_start < $slot_unix_end);
				if ($found)
				{
					$row = $booking_row;
					break;
				}
			}
		}

		return $row;

	} // end get_slot_booking


	/**
	 * Display a list of all the bookings for the the current viewing date for each room
	 *
	 * (provide links to cancel and book also)
	 * @access public
	 * @return the view html
	 **/
	function output_rooms_view($tag_data='')
	{
		global $TMPL, $DB, $SESS, $LOC;

		$tag_data = ($tag_data == '' ? $TMPL->tagdata : $tag_data);

		preg_match("'\{rooms_view\}(.+)\{(/|&#47;)rooms_view\}'siU", $tag_data, $matches);
		$view_html = $matches[1];

		$view_html = $this->output_locations_list($view_html);
		$view_html = $this->output_rooms_list($view_html);
		$view_html = $this->output_available_dates_list($view_html);

		$self = $_SERVER['PHP_SELF'];

		$current_view_date = $this->get_current_view_date();
		$day = $current_view_date['d'];
		$month = $current_view_date['m'];
		$year = $current_view_date['y'];

		$unix_date = mktime (0, 0, 0, $month, $day, $year); // current viewing day as a timestamp
		$end_unix_date = mktime (23, 59, 59, $month, $day, $year); // the end of the current viewing day
		$day_seconds = (24 * 60 * 60);

		$max_advance_booking_days = $this->settings['max_advance_booking_days'];
		$today = time();
		$start_of_today = mktime (0, 0, 0, date ("m"), date ("d"), date ("Y"));
		$end_of_today = mktime (23, 23, 59, date ("m"), date ("d"), date ("Y"));
		$last_booking_day = mktime (0, 0, 0, date ("m"), date ("d") + $max_advance_booking_days, date ("Y"));

		$previous_unix_day = mktime (0, 0, 0, $month, $day - 1, $year);
		$previous_date = date ("Y-m-d", $previous_unix_day);

		$next_unix_day = mktime (0, 0, 0, $month, $day + 1, $year);
		$next_date = date ("Y-m-d", $next_unix_day);

		$previous_link_html = "";
		if ($previous_unix_day >= $start_of_today)
		{
			$previous_link_html = "<a href=\"$self?action=rooms_view&amp;booking_date=$previous_date&amp;location_id=$this->location_id\" \\1 >\\2</a>";
		}

		$next_link_html = "";
		if ($next_unix_day <= $last_booking_day) // if next day is passed the last advance booking date
		{
			$next_link_html = "<a href=\"$self?action=rooms_view&amp;booking_date=$next_date&amp;location_id=$this->location_id\" \\1 >\\2</a>";
		}

		// put the appropriate URLs in

		$week_view_url = $self . "?booking_date=$this->booking_date&amp;room_id=$this->room_id&amp;action=week_view";
		$view_html = str_replace("{week_view_url}", $week_view_url, $view_html);

		$calendar_view_url = $self . "?room_id=$this->room_id&amp;action=calendar_view";
		$view_html = str_replace("{calendar_url}", $calendar_view_url, $view_html);
		$view_html = preg_replace("'{previous_day_link([^}]*)\}(.+)\{(/|&#47;)previous_day_link\}'si", $previous_link_html, $view_html);
		$view_html = preg_replace("'{next_day_link([^}]*)\}(.+)\{(/|&#47;)next_day_link\}'si", $next_link_html, $view_html);

		// #### deal with displaying the bookings ####

		$logged_in_member_id = $SESS->userdata['member_id'];

		// get all the bookings for each of the rooms for the current viewing day
		$room_booking_rows = array();
		$slot_times = $this->get_slot_times($day, $month, $year);

		foreach ($this->rooms as $room_id => $room_row)
		{
			$rows = $this->get_booking_rows($this->booking_date, $room_id); // array(unix_start  => unix_end, ...)

			if (sizeof($rows) > 0)
			{
				$room_booking_rows[$room_id] = $rows;
			}
		}

		// get contents of booking_slot tags
		preg_match("'\{booking_slot[^}]*\}(.+)\{(/|&#47;)booking_slot\}'siU", $view_html, $matches);
		$booking_slot_content = $matches[1];

		// get content of slot room row tags
		preg_match("'\{slot_room_row[^}]*\}(.+)\{(/|&#47;)slot_room_row\}'siU", $booking_slot_content, $matches);
		$slot_room_row_content = $matches[1];

		$slots_output_html = '';
		$slot_html = '';
		$slot_room_row_html = '';

		$cancels_shown = array(); // record whether the cancel link was shown for a booking
		$end_bookings_shown = array(); // record whether the end booking link was shown for a booking
		$bookings_started = array(); // keep track of which bookings have started

		$slot_row_index = 0;

		$room_current_bookings = array();
		$current_booking_row = array();

		// do each slot row in turn for each room
		foreach ($slot_times as $slot_unix_start => $slot_unix_end)
		{
			$slot_start_time = date ("H:i", $slot_unix_start);
			$slot_end_time = date ("H:i", $slot_unix_end);
			$slot_time = "$slot_start_time - $slot_end_time";
			$booking_date = date("Y-m-d", $slot_unix_start);

			$slot_html = $booking_slot_content;

			$slot_row_html = '';

			// iterate through each room to display
			foreach ($this->rooms as $room_id => $room_row)
			{
				$booking_id = '';
				$booking_time ='';
				$meeting_name = '';
				$owner = '';
				$booking_url = '';
				$cancel_link_html = '';
				$end_link_html = '';
				$is_booking_start = false;
				$is_booking_end = false;

				$slot_cell_html = $slot_room_row_content;

				// bookings for this room
				$booking_rows = $room_booking_rows[$room_id];

				// locate a meeting that started during this slot
				$row = $this->get_slot_booking($slot_unix_start, $booking_rows);

				if (!empty($row))
				{
					$room_current_bookings[$room_id] = $row;
					$booking_id = $row['booking_id'];
					$bookings_started[$booking_id] = $row;
					$is_booking_start = true;
//					print("<br/>$slot_time: booking started in {$room_row['room_name']}<br/>");//TMP
				}

				$current_booking_row = $room_current_bookings[$room_id];

//				if (!empty($current_booking_row))
//					print("slot: ".date("H:i",$slot_unix_start)."-".date("H:i",$slot_unix_end)." room: {$room_row['room_name']} ");//TMP

				$is_slot_booked = (sizeof($current_booking_row) > 0);


				$is_past = $this->is_requested_booking_time_past($slot_unix_start); // link to nothing if time has past
				$is_in_slot = $this->is_booking_in_current_slot($slot_unix_start);

				// slot NOT booked, so replace {if not_slot_booked) conditional tag content
				if (empty($current_booking_row))
				{
					if (empty($SESS->userdata['member_id']))
					{
						$booking_url = "javascript:alert('You must be logged in to make a booking')";
					}
					else
					{
						$booking_url = ($is_past && !$is_in_slot ?  "javascript:alert('You cannot make a booking in the past')" :
																	$this->booking_script_url . "?booking_date=$this->booking_date&amp;room_id=$room_id&amp;start_time=$slot_unix_start");
					}
				}
				// slot IS booked, so replace {if slot_booked) conditional tag content
				else
				{
//					print(" is booking start? ".($is_booking_start ? 'YES' : 'no')." ");//TMP

					$unix_start = $current_booking_row['unix_start'];
					$unix_end = $current_booking_row['unix_end'];
					$is_booking_end = ($unix_end == $slot_unix_end); // booking ends in this slot

					$booking_duration = ($unix_end - $unix_start);
					$slot_duration = ($slot_unix_end - $slot_unix_start);
					$slot_count = ceil($booking_duration / $slot_duration);

					$booking_id = $current_booking_row['room_booking_id'];
					$meeting_name = stripslashes($current_booking_row['activity_name']);
				 	$room_id = $current_booking_row['room_id'];
				 	$room_name = $current_booking_row['room_name'];
				 	$hex_colour = $current_booking_row['hex_colour'];
				 	$extension = $current_booking_row['extension'];
					$start =  date ("H:i", $unix_start);
					$end = date ("H:i", $unix_end);
					$booking_time = "$start - $end";

//					if ($is_booking_end)
//						print("<br/>$slot_time: booking [$booking_time: '$meeting_name'] ended in {$room_row['room_name']}<br/>");//TMP

					$screen_name = $current_booking_row['screen_name'];
					$username = $current_booking_row['username'];
					$owner = (empty($screen_name) ? $username : $screen_name);
					$owner_mailto = "";
					$email = $current_booking_row['email'];

					if (!empty($email))
						$owner_mailto = "<a title=\"Send email to booking owner\" href=\"mailto:$owner <$email>?subject=Your room booking for $booking_date ($booking_time) in '$room_name'\">$owner</a>";

					// only allow cancel if logged in as admin, if you own the booking and if it is in the future
					$is_cancel_allowed = (($this->is_admin() || $row['user_idFK'] == $logged_in_member_id) &&
										  $unix_end >= $today);

					$cancel_link_html = "";					  
					if ($is_cancel_allowed) // use the link text and extras from the {cancel_link} tag if allowed to show it
					{
						$cancel_link_html = "<a onclick=\"return confirm('Really cancel this booking?');\" href=\"$self?booking_date=$this->booking_date&amp;booking_id=$booking_id&amp;action=cancel_booking\" \\1 >\\2</a>";
					}
					
					// only allow end booking if logged in as admin, if you own the booking and it's not a single time-slot and the meeting is still in progress
					$is_in_progress = ($today >= $unix_start && $today <= $unix_end);
					$is_end_allowed = (($this->is_admin() || $row['user_idFK'] == $logged_in_member_id) &&
									  $is_in_progress && !($is_booking_start && $is_booking_end));

					$end_link_html = "";						
					if ($is_end_allowed) // use the link text and extras from the {end_link} tag if allowed to show it
					{
						$end_link_html = "<a onclick=\"return confirm('Really end this booking now?');\" href=\"$self?booking_date=$this->booking_date&amp;booking_id=$booking_id&amp;action=end_booking\" \\1 >\\2</a>";
					}
					
					$booking_unix_start = $current_booking_row['unix_start'];
					$cancel_link_html = ($cancels_shown[$room_id][$booking_unix_start] ? "" : $cancel_link_html);
					$end_link_html = ($end_bookings_shown[$room_id][$booking_unix_start] ? "" : $end_link_html);
					$slot_cell_html = preg_replace("'{cancel_link([^}]*)\}(.+)\{(/|&#47;)cancel_link\}'siU", $cancel_link_html, $slot_cell_html);
					$slot_cell_html = preg_replace("'{end_link([^}]*)\}(.+)\{(/|&#47;)end_link\}'siU", $end_link_html, $slot_cell_html);
					$cancels_shown[$room_id][$booking_unix_start] = true;
					$end_bookings_shown[$room_id][$booking_unix_start] = true;

					$day_link_url = "$self?booking_date=$booking_date&amp;room_id=$room_id&amp;action=day_view";
					$day_link_html = "<a href=\"$day_link_url\" \\1 >\\2</a>";
					$slot_cell_html = preg_replace("'{day_link([^}]*)\}(.+)\{(/|&#47;)day_link\}'siU", $day_link_html, $slot_cell_html);
				}

//				print("slot time: $slot_time<br/>");//TMP

				$slot_cell_html = str_replace("{booking_script_url}", $booking_url, $slot_cell_html);
				$slot_cell_html = str_replace("{meeting_name}", $meeting_name, $slot_cell_html);
				$slot_cell_html = str_replace("{booking_owner}", $owner, $slot_cell_html);
				$slot_cell_html = str_replace("{booking_owner_email}", $email, $slot_cell_html);
				$slot_cell_html = str_replace("{booking_owner_mailto}", $owner_mailto, $slot_cell_html);
				$slot_cell_html = str_replace("{booking_time}", $booking_time, $slot_cell_html);
				$slot_cell_html = str_replace("{slot_count}", $slot_count, $slot_cell_html);

				// replace the conditionals
				$is_start_replace = "";
				$is_end_replace = "";
				$is_single_slot_replace = "";
				$is_mid_booking_replace = "";
				$is_not_mid_booking_replace = "";
				$is_next_slot_booked_replace = "";
				$is_past_replace = "";
				$is_not_past_replace = "";

				if ($is_slot_booked)
				{
					$is_not_mid_booking_replace = "\\1";

					if ($is_booking_start && $is_booking_end) // booking is a single-slot booking
					{
						$is_single_slot_replace = "\\1";
//						print("[$booking_time: '$meeting_name'] is single slot booking<br/>");//TMP
					}
					else
					{
						if ($is_booking_start)
						{
							$is_start_replace = "\\1";
//							print("[$booking_time: '$meeting_name'] is booking start<br/>");//TMP
						}
						else if ($is_booking_end)
						{
							$is_end_replace = "\\1";
//							print("[$booking_time: '$meeting_name'] is booking end<br/>");//TMP
						}
						else // current slot is in the middle of a booking somewhere
						{
							$is_mid_booking_replace = "\\1";
							$is_not_mid_booking_replace = "";
//							print("[$booking_time: '$meeting_name'] is mid-booking<br/>");//TMP
						}
					}

					$is_booked_replace = "\\1";
					$is_not_booked_replace = "";
				}
				else // not booked
				{
					$is_booked_replace = "";
					$is_not_booked_replace = "\\1";

					$is_past = ($is_past && !$is_in_slot);
					if ($is_past)
					{
						$is_past_replace = "\\1";
						$is_not_past_replace = "";
					}
					else
					{
						$is_past_replace = "";
						$is_not_past_replace = "\\1";
					}
				}

				// check if next slot has a booking
				$temp_times = array_keys($slot_times);
				$next_slot_start = $temp_times[$slots_index + 1];
				$row = $this->get_slot_booking($next_slot_start, $booking_rows);
				if (!empty($row))
				{
					$is_next_slot_booked_replace = "\\1";
				}

				// do the replacements
				$slot_cell_html = preg_replace("'\{if next_slot_booked[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_next_slot_booked_replace, $slot_cell_html);
				$slot_cell_html = preg_replace("'\{if booking_start[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_start_replace, $slot_cell_html);
				$slot_cell_html = preg_replace("'\{if booking_end[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_end_replace, $slot_cell_html);
				$slot_cell_html = preg_replace("'\{if single_slot[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_single_slot_replace, $slot_cell_html);
				$slot_cell_html = preg_replace("'\{if mid_booking[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_mid_booking_replace, $slot_cell_html);
				$slot_cell_html = preg_replace("'\{if not_mid_booking[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_not_mid_booking_replace, $slot_cell_html);

				$slot_cell_html = preg_replace("'\{if slot_in_past[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_past_replace, $slot_cell_html);
				$slot_cell_html = preg_replace("'\{if not_slot_in_past[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_not_past_replace, $slot_cell_html);
//				print("<hr/><div style=\"background-color: #FFF;\">".htmlspecialchars($slot_cell_html)."</div><hr/><br/><br/>");//TMP

				// these must come last because of nested conditionals
				$slot_cell_html = preg_replace("'\{if slot_booked[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_booked_replace, $slot_cell_html);
				$slot_cell_html = preg_replace("'\{if not_slot_booked[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_not_booked_replace, $slot_cell_html);

				$slot_row_html .= "$slot_cell_html";

				if ($current_booking_row['unix_end'] == $slot_unix_end)
				{
					$current_booking_row = null; // current booking ended in this slot
					$room_current_bookings[$room_id] = null;
				}

				// see if the current booking ends during this slot
				if ($current_booking_row != null && sizeof($booking_rows) > 0)
				{
					$found = false;
					foreach ($booking_rows as $unix_start => $booking_row)
					{
						$unix_end = $booking_row['unix_end'];
						$found = ($unix_end < $slot_unix_end && $unix_end > $slot_unix_start);
						if ($found)
						{
							$room_current_bookings[$room_id] = null;
							$current_booking_row = null;
							break;
						}
					}
				}
			}

			// check if current slot
			$current_times = $this->get_current_slot_times();
			$keys = array_keys($current_times);
			$current_slot_start = $keys[0];
			$is_current_slot = ($slot_unix_start == $current_slot_start);
			$is_current_slot_replace = ($is_current_slot ? "\\1" : "");
//			print("[$slot_time] ($slot_unix_start - $slot_unix_end) current slot start: $current_slot_start is current ? ($is_current_slot)<br/>");//TMP
			$slot_html = preg_replace("'\{if current_slot[^}]*\}(.+)\{(/|&#47;)if\}'siU", $is_current_slot_replace, $slot_html);

			// replace the slot time tags
			$slot_html = str_replace("{slot_time}", $slot_time, $slot_html);

			// replace the slot row tag set with the combined set of slot day info for the week
			$slot_html = preg_replace("'\{slot_room_row[^}]*\}(.+)\{(/|&#47;)slot_room_row\}'si", $slot_row_html, $slot_html);

			$slots_output_html .= $slot_html;

			$slot_row_index++;
		}

		$view_html = str_replace("{booking_date}", $this->booking_display_date, $view_html);

		$view_html = str_replace("{room_name}", $room_name, $view_html);
		$view_html = str_replace("{hex_color}", $hex_color, $view_html);

		// replace the booking slot tag set with the combined set of booking entries
		$view_html = preg_replace("'\{booking_slot[^}]*\}(.+)\{(/|&#47;)booking_slot\}'si", $slots_output_html, $view_html);

		// output the booking entries in the place specified in the template
		$view_html = preg_replace("'\{bookings[^}]*\}(.+)\{(/|&#47;)bookings\}'si", "\\1", $view_html);

		// output the rooms view in the place specified in the template
		$output = preg_replace("'\{rooms_view\}(.+)\{(/|&#47;)rooms_view\}'si", $view_html, $tag_data);

		return $output;

	}	// end output_rooms_view


	/**
	 * Replace template tags to output info and nvaigation links for each
	 * meeting room
	 *
	 * {rooms_list}
	 * 		...
	 * 		{room_detail}
	 * 			...
	 * 		{/room_detail}
	 * 		...
	 * {/rooms_list}
	 *
	 **/
	function output_rooms_list($tag_data='')
	{
//		print("output_rooms_list()<br/>");//TMP

		global $TMPL;

		$self = $_SERVER['PHP_SELF'];

		$tag_data = ($tag_data == '' ? $TMPL->tagdata : $tag_data);

//		print("<div style=\"border: solid 1px; background-color: #FFF;\">".htmlspecialchars($tag_data)."</div>");//TMP

		preg_match("'\{room_detail[^}]*\}(.+)\{(/|&#47;)room_detail\}'siU", $tag_data, $matches);
		$room_detail_content = $matches[1];
//		print("<div style=\"border: solid 1px; background-color: #FFF;\">".htmlspecialchars($room_detail_content)."</div>");//TMP

		// do each of the room rows for the room_detail
		$rooms_list_html = '';

//		print("<div style=\"border: solid 1px; background-color: #FFF;\">outputting room rows</div>");//TMP

		foreach ($this->rooms as $room_id => $row)
		{
			// output the values of the room attributes
			preg_match("'\{room_attributes[^}]*\}(.+)\{(/|&#47;)room_attributes\}'siU", $room_detail_content, $matches);
			$attributes_content = $matches[1];
			$attributes_html = $this->output_room_attributes($attributes_content, $row);
			$room_detail_html = preg_replace("'\{room_attributes[^}]*\}(.+)\{(/|&#47;)room_attributes\}'siU", $attributes_content, $attributes_html);

			$room_name = $row['room_name'];
			$room_description = $row['room_description'];
			$hex_colour = $row['hex_colour'];
			$extension = $row['extension'];
			$room_location = $row['location_name'];
			//remove 'house' from location
			$room_location = str_replace(" House", "", $room_location);

			$room_detail_html = str_replace("{booking_date}", $this->booking_display_date, $room_detail_html);
			$room_detail_html = str_replace("{booking_date_internal}", $this->booking_date, $room_detail_html);
			$room_detail_html = str_replace("{room_name}", $room_name, $room_detail_html);
			$room_detail_html = str_replace("{room_description}", $room_description, $room_detail_html);
			$room_detail_html = str_replace("{room_id}", $room_id, $room_detail_html);
			$room_detail_html = str_replace("{hex_colour}", $hex_colour, $room_detail_html);
			$room_detail_html = str_replace("{extension}", $extension, $room_detail_html);
			$room_detail_html = str_replace("{room_location}", $room_location, $room_detail_html);

			// put the navigation links in to the different views
			$base_url = $self . "?booking_date=$this->booking_date&amp;room_id=$room_id";
			$day_view_url = $base_url . "&amp;action=day_view";
			//$week_view_url = $base_url . "&amp;action=week_view";
			//$calendar_view_url = $base_url . "&amp;action=calendar_view";

			$day_view_link_html = "<a href=\"$day_view_url\" \\1 >\\2</a>";
			$room_detail_html = preg_replace("'{day_view_link([^}]*)\}(.+)\{(/|&#47;)day_view_link\}'siU", $day_view_link_html, $room_detail_html);

/*			$week_view_link_html = "<a href=\"$week_view_url\" \\1 >\\2</a>";
			$room_detail_html = preg_replace("'{week_view_link([^}]*)\}(.+)\{(/|&#47;)week_view_link\}'siU", $week_view_link_html, $room_detail_html);

			$calendar_view_link_html = "<a href=\"$calendar_view_url\" \\1 >\\2</a>";
			$room_detail_html = preg_replace("'{calendar_view_link([^}]*)\}(.+)\{(/|&#47;)calendar_view_link\}'siU", $calendar_view_link_html, $room_detail_html);
*/
			$rooms_list_html .= "$room_detail_html";
		}

//		print("<div style=\"border: solid 1px; background-color: #FFF;\">".htmlspecialchars($rooms_list_html)."</div>");//TMP

		// replace the {room_detail} tag set with the combined set of room entries
		$tag_data = preg_replace("'\{room_detail[^}]*\}(.+)\{(/|&#47;)room_detail\}'siU", $rooms_list_html, $tag_data);

		// do the first row (for the header)
//		print("<div style=\"border: solid 1px; background-color: #FFF;\">outputting header</div>");//TMP

		$tmp = array_values($this->rooms);
		$first_row = $tmp[0];
		$tag_data = $this->output_room_attributes($tag_data, $first_row);
//		print("<div style=\"border: solid 1px; background-color: #FFF;\">tag_data: ".htmlspecialchars($tag_data)."</div>");//TMP
		$tag_data = preg_replace("'\{room_attributes[^}]*\}(.+)\{(/|&#47;)room_attributes\}'siU", "\\1", $tag_data);
//		print("<div style=\"border: solid 1px; background-color: #FFF;\">tag_data: ".htmlspecialchars($tag_data)."</div>");//TMP

		// output the {rooms_list} in the place specified in the template
		$output = preg_replace("'\{rooms_list[^}]*\}(.+)\{(/|&#47;)rooms_list\}'si", "\\1", $tag_data);

		return $output;

	} // end output_rooms_list


	/**
	 * Replace template tags to output info and nvaigation links for each
	 * room location
	 *
	 * {locations_list}
	 * 		...
	 * 		{location_detail}
	 * 			...
	 * 		{/location_detail}
	 * 		...
	 * {/locations_list}
	 *
	 **/
	function output_locations_list($tag_data='')
	{
//		print("output_locations_list()<br/>");//TMP
		global $TMPL;

		$self = $_SERVER['PHP_SELF'];

		$tag_data = ($tag_data == '' ? $TMPL->tagdata : $tag_data);

//		print("<div style=\"border: solid 1px; background-color: #FFF;\">".htmlspecialchars($tag_data)."</div>");//TMP

		preg_match("'\{locations_list[^}]*\}(.+)\{(/|&#47;)locations_list\}'siU", $tag_data, $matches);
		$locations_list_content = $matches[1];

		preg_match("'\{location_detail[^}]*\}(.+)\{(/|&#47;)location_detail\}'siU", $locations_list_content, $matches);
		$location_detail_content = $matches[1];
//		print("<div style=\"border: solid 1px; background-color: #FFF;\">".htmlspecialchars($location_detail_content)."</div>");//TMP

		// do each of the location rows for the location_detail
		$locations_list_html = $locations_list_content;

		$base_url = $self . "?booking_date=$this->booking_date&amp;action=rooms_view";

		$all_locations_link_html = "<a href=\"$base_url\" \\1 >\\2</a>";
		$locations_list_html = preg_replace("'{all_locations_link([^}]*)\}(.+)\{(/|&#47;)all_locations_link\}'siU", $all_locations_link_html, $locations_list_html);

//		print("<div style=\"border: solid 1px; background-color: #FFF;\">outputting location rows</div>");//TMP

//		print_r($locations);//TMP

		foreach ($this->locations as $location_id => $row)
		{
			$location_name = $row['location_name'];
			$location_detail_html .= $location_detail_content;

			$location_detail_html = str_replace("{location_id}", $location_id, $location_detail_html);
			$location_detail_html = str_replace("{location_name}", $location_name, $location_detail_html);

			// put the navigation links in to the different views
			$rooms_view_url = $base_url . "&amp;location_id=$location_id";

			$rooms_view_link_html = "<a href=\"$rooms_view_url\" \\1 >\\2</a>";
			$location_detail_html = preg_replace("'{rooms_view_link([^}]*)\}(.+)\{(/|&#47;)rooms_view_link\}'siU", $rooms_view_link_html, $location_detail_html);
		}

		// replace the {location_detail} tag set with the combined set of location entries
		$locations_list_html = preg_replace("'\{location_detail[^}]*\}(.+)\{(/|&#47;)location_detail\}'siU", $location_detail_html, $locations_list_html);

		$output = preg_replace("'\{locations_list[^}]*\}(.+)\{(/|&#47;)locations_list\}'si", $locations_list_html, $tag_data);

		return $output;

	} // end output_locations_list


	/**
	 * Replace template tags to output info and nvaigation links for each
	 * room date
	 *
	 * {available_dates_list}
	 * 		...
	 * 		{date_info}
	 * 		... {internal_date} .. {display_date} ... {if booking_date}...{/if}
	 * 		{/date_info}
	 * 		...
	 * {/available_dates_list}
	 *
	 **/
	function output_available_dates_list($tag_data='')
	{
//		print("output_dates_list()<br/>");//TMP
		global $TMPL;

		$self = $_SERVER['PHP_SELF'];

		$tag_data = ($tag_data == '' ? $TMPL->tagdata : $tag_data);

//		print("<div style=\"border: solid 1px; background-color: #FFF;\">".htmlspecialchars($tag_data)."</div>");//TMP

		preg_match("'\{available_dates_list[^}]*\}(.+)\{(/|&#47;)available_dates_list\}'siU", $tag_data, $matches);
		$dates_list_content = $matches[1];

		preg_match("'\{date_info[^}]*\}(.+)\{(/|&#47;)date_info\}'siU", $dates_list_content, $matches);
		$date_info_content = $matches[1];

		$dates_list_html = $dates_list_content;

		$on_change_url = $_SERVER['PHP_SELF'] . "?action=$this->action&amp;room_id=$this->room_id&amp;location_id=$this->location_id&amp;booking_date=";
		$dates_list_html = str_replace("{on_change_url}", $on_change_url, $dates_list_html);
		
		$max_advance_booking_days = $this->settings['max_advance_booking_days'];

		$date_parts = explode("-", $this->booking_date);
		list($y, $m, $d) = $date_parts;
		$start_of_booking_day = mktime (0, 0, 0, $m, $d, $y);

		$today = time();
		$d = date ("d", $today);
		$m = date ("m", $today);
		$y = date ("Y", $today);

		$start_of_today = mktime (0, 0, 0, $m, $d, $y);		
		
		for ($i = 0; $i <= $max_advance_booking_days; $i++)
		{
			$date_info_html .= $date_info_content;

			$date = mktime (0, 0, 0, $m, $d + $i, $y);
			$is_booking_date = ($date == $start_of_booking_day);
			
			$internal_date = date ("Y", $date) . "-" . date ("m", $date) . "-" . date ("d", $date);
			$display_date = date ("l jS F", $date);
			
			$date_info_html = str_replace("{internal_date}", $internal_date, $date_info_html);
			$date_info_html = str_replace("{display_date}", $display_date, $date_info_html);

//			print("$display_date<br/>");//TMP
			
			$replacement = ($is_booking_date ? "\\1" : "");
	  		$date_info_html = preg_replace("'\{if booking_date[^}]*\}(.+)\{(/|&#47;)if\}'siU", $replacement, $date_info_html);   							
		}

		// replace the {date_info} tag set with the combined set of date entries
		$dates_list_html = preg_replace("'\{date_info[^}]*\}(.+)\{(/|&#47;)date_info\}'siU", $date_info_html, $dates_list_html);

		$output = preg_replace("'\{available_dates_list[^}]*\}(.+)\{(/|&#47;)available_dates_list\}'si", $dates_list_html, $tag_data);

		return $output;

	} // end output_available_dates_list


	/**
	 *
	 * @param $exceptions List of fields to ignore
	 * @param $tag_data HTML from the template, should contain the following tags:
	 *
	 * 	{room_attribute} (required)
	 * 		{attribute_label} (optional)
	 * 		{/attribute_value} (optional)
	 * 	{/room_attribute}
	 **/
	function output_room_attributes($tag_data="", $room_data_row,
		$exceptions=array('room_id', 'room_description', 'location_id', 'location_idFK'))
	{
		global $TMPL, $LANG;

		$LANG->fetch_language_file('ncb_rooms');

//		print("<hr/><div style=\"background-color: #FFF;\">LANG<br/><pre>");//TMP
//		print_r($LANG);//TMP
//		print("</pre></div><hr/>");//TMP

		$tag_data = ($tag_data == '' ? $TMPL->tagdata : $tag_data);

		preg_match("'\{room_attribute\}(.+)\{(/|&#47;)room_attribute\}'siU", $tag_data, $matches);
		$attribute_content = $matches[1];
//		print("<div style=\"border: solid 1px; background-color: #FFF;\">attribute_content: ".htmlspecialchars($attribute_content)."</div>");//TMP

		$room_attributes_html = '';

		foreach ($room_data_row as $field => $value)
		{
//			print("<div style=\"border: solid 1px; background-color: #FFF;\">field => value: $field => $value in exceptions? [".array_search($field, $exceptions)."]</div>");//TMP

			$attribute_html = '';

 			if (array_search($field, $exceptions) === FALSE)
			{
				$attribute_html = $attribute_content;

				$label = strtolower($LANG->line($field));
				$label = (empty($label) ? $field : $label);
				$label = ucfirst($label);

				$attribute_html = str_replace("{attribute_label}", $label, $attribute_html);
				$attribute_html = str_replace("{attribute_value}", $value, $attribute_html);

//				print("<div style=\"border: solid 1px; background-color: #FFF;\">attribute_html: ".htmlspecialchars($attribute_html)."</div>");//TMP
				$room_attributes_html .= "$attribute_html";
			}
		}

		$output = preg_replace("'\{room_attribute\}(.+)\{(/|&#47;)room_attribute\}'si", $room_attributes_html, $tag_data);

		return $output;

	} // end output_room_attributes


	/**
	 * Show quick links for all rooms
	 * use the following tags in desired templates, output  xhtml links and unformatted text
	 *
	 * {exp:ncb_rooms:calendar switch="calendarToday|calendarCell" meeting_room_url="/working-here/meeting-rooms/" booking_script_url="/working-here/book-room/" show_rooms_list="no" action="quick_links"}
	 * 	{room_list}
	 * 		{day_view_link title="View day bookings"}{room_name}{/day_view_link}&nbsp;
     *			{book_now_link title="Book now"}<br />
     *		{/room_list}
     * {/exp:ncb_rooms:calendar}
     *
     * example xhtml, free room:
     * <a href="/working-here/meeting-rooms/?booking_date=2007-03-12&amp;room_id=4&amp;action=day_view" title="View day bookings">Atlas Park</a>&nbsp;
	 *	<a href="/working-here/book-room/?booking_date=2007-03-12&amp;room_id=4&amp;start_time=1173718800" title="Book now">Free</a><br/>
	 *
	 * example xhtml, room in use:
	 *	<a href="/working-here/meeting-rooms/?booking_date=2007-03-12&amp;room_id=5&amp;action=day_view" title="View day bookings">Cantha</a>&nbsp;
	 * Busy<br/>
	 */
	function output_quick_links($tag_data='')
	{
		global $TMPL;
		$tag_data = ($tag_data == '' ? $TMPL->tagdata : $tag_data);

		//get current slot times
		$slot_info = $this->get_current_slot_times();

		//setup rooms list content
		preg_match("'\{room_list[^}]*\}(.+)\{(/|&#47;)room_list\}'siU", $tag_data, $matches);
		$room_list_tags = $matches[1];
		$room_list_html = '';

		foreach ($this->rooms as $room_id => $row)
		{
			$room_name = $row['room_name'];
			$room_list_content = str_replace("{room_name}", $room_name, $room_list_tags);
			
			$room_description = $row['room_description'];
			$room_list_content = str_replace("{room_description}", $room_description, $room_list_content);
			
			$room_size = $row['room_size'];
			$room_list_content = str_replace("{room_size}", $room_size, $room_list_content);
			
			$room_colour = $row['hex_colour'];
			$room_list_content = str_replace("{hex_colour}", $room_colour, $room_list_content);
			
			$has_video_conferencing = $row['has_video_conferencing'];
			$room_list_content = str_replace("{has_video_conferencing}", $has_video_conferencing, $room_list_content);
			
			$extension = $row['extension'];
			$room_list_content = str_replace("{extension}", $extension, $room_list_content);
			
			$login = $row['login'];
			$room_list_content = str_replace("{login}", $login, $room_list_content);
			
			$password = $row['password'];
			$room_list_content = str_replace("{password}", $password, $room_list_content);

			//set basic day view link
			$day_view_url = $this->meeting_room_url."?booking_date=$this->booking_date&amp;room_id=$room_id&amp;action=day_view";
			$day_view_link_html = "<a href=\"$day_view_url\" \\1 >\\2</a>";
			$room_list_content = preg_replace("'{day_view_link([^}]*)\}(.+)\{(/|&#47;)day_view_link\}'siU", $day_view_link_html, $room_list_content);

			//set current slot booking link
			$current_slot_link_html = '';
			$slot_info = $this->get_current_slot_times();
			$keys = array_keys($slot_info);
			$unix_start = $keys[0];
			$unix_end = $slot_info[$unix_start];

			if($this->is_slot_free($room_id, $unix_start, $unix_end)) {
				$current_slot_url = $this->booking_script_url."?booking_date=$this->booking_date&amp;room_id=$room_id&amp;start_time=$unix_start";
				$current_slot_link_html = "<a href=\"$current_slot_url\" \\1>Free</a>";
			}
			else {
				$current_slot_link_html = "Busy";
			}
			$room_list_content = preg_replace("'{book_now_link([^}]*)\}'siU", $current_slot_link_html, $room_list_content);

			$room_list_html .= $room_list_content;
		}

		// output the {rooms_list} in the place specified in the template
		$output = preg_replace("'\{room_list[^}]*\}(.+)\{(/|&#47;)room_list\}'si", $room_list_html, $tag_data);

		return $output;
	}

	/**
	 * @return true if chosen slot is totally free for the room id given
	 * false othewise
	 */
	function is_slot_free($room_id, $start_time, $end_time)
	{
		global $DB;
		$slot_free = true;

		$sql = "SELECT exp_ncb_room_bookings.*
					FROM exp_ncb_room_bookings, exp_ncb_rooms, exp_members
					WHERE room_idFK = '$room_id'
					AND ( ('".date('Y-m-d H:i:s', $start_time)."' >= start_time AND '".date('Y-m-d H:i:s', $start_time)."' < end_time) OR
						 	('".date('Y-m-d H:i:s', $start_time)."' <= start_time AND '".date('Y-m-d H:i:s', $end_time)."' > start_time) ) ";
//		print($start_time." ".date('Y-m-d H:i:s', $start_time)." ");

		$query = $DB->query($sql);

		if ($query->num_rows > 0) {
	    	$slot_free = false;
	    }

	    return $slot_free;
	}


	/**
	 * Show main calendar view
	 */
/*    function output_calendar_view($tag_data='')
    {
    	global $LANG, $TMPL, $LOC, $IN, $DB, $FNS, $PREFS, $SESS;

		// Rick is using some funky conditional stuff for the calendar, so
		// we have to reassign the var_cond array using the legacy conditional
		// parser.  Bummer, but whatcha going to do?

		if ($tag_data != '')
		{
			$TMPL->tagdata = $tag_data;
		}

		$TMPL->var_cond = $FNS->assign_conditional_variables($TMPL->tagdata, SLASH, LD, RD);

//		print("<hr/><div style=\"background-color: #FFF;\">");//TMP
//		print_r($TMPL->var_cond);//TMP
//		print("</div><hr/>");//TMP


		// ----------------------------------------
		//  Determine the Month and Year
		// ----------------------------------------

		$current_view_date = $this->get_current_view_date();
		$year = $current_view_date['y'];
		$month = $current_view_date['m'];

		// ----------------------------------------
		//  Set Unix timestamp for the given month/year
		// ----------------------------------------

		$local_date = mktime(12, 0, 0, $month, 1, $year);
		// $local_date = $LOC->set_localized_time($local_date);

		// ----------------------------------------
		//  Determine the total days in the month
		// ----------------------------------------

        $adjusted_date = $LOC->adjust_date($month, $year);

        $month	= $adjusted_date['month'];
        $year	= $adjusted_date['year'];

		$total_days = $LOC->fetch_days_in_month($month, $year);

		$previous_date 	= mktime(12, 0, 0, $month-1, 1, $year);
		$next_date 		= mktime(12, 0, 0, $month+1, 1, $year);

		// ----------------------------------------
		//	Set the starting day of the week
		// ----------------------------------------

		// This can be set using a parameter in the tag:  start_day="saturday"
		// By default the calendar starts on sunday

		$start_days = array('sunday' => 0, 'monday' => 1, 'tuesday' => 2, 'wednesday' => 3, 'thursday' => 4, 'friday' => 5, 'saturday' => 6);

		$start_day = (isset($start_days[$TMPL->fetch_param('start_day')])) ? $start_days[$TMPL->fetch_param('start_day')]: 0;

		$date = getdate($local_date);
		$day  = $start_day + 1 - $date["wday"];

		while ($day > 1)
		{
    			$day -= 7;
		}

		// ----------------------------------------
		//  {previous_path="weblog/index"}
		// ----------------------------------------

		// This variables points to the previous month

		if (preg_match_all("#".LD."previous_path=(.+?)".RD."#", $TMPL->tagdata, $matches))
		{
			$adjusted_date = $LOC->adjust_date($month - 1, $year, TRUE);

			foreach ($matches['1'] as $match)
			{
				$path = $FNS->create_url($match).$adjusted_date['year'].'/'.$adjusted_date['month'].'/';
				$path .= "?room_id=$this->room_id&amp;action=calendar_view";

				$TMPL->tagdata = preg_replace("#".LD."previous_path=.+?".RD."#", $path, $TMPL->tagdata, 1);
			}
		}

		// ----------------------------------------
		//  {next_path="weblog/index"}
		// ----------------------------------------

		// This variables points to the next month

		if (preg_match_all("#".LD."next_path=(.+?)".RD."#", $TMPL->tagdata, $matches))
		{
			$adjusted_date = $LOC->adjust_date($month + 1, $year, TRUE);

			foreach ($matches['1'] as $match)
			{
				$path = $FNS->create_url($match).$adjusted_date['year'].'/'.$adjusted_date['month'].'/';
				$path .= "?room_id=$this->room_id&amp;action=calendar_view";

				$TMPL->tagdata = preg_replace("#".LD."next_path=.+?".RD."#", $path, $TMPL->tagdata, 1);
			}
		}

		// ----------------------------------------
		//  {date format="%m %Y"}
		// ----------------------------------------

		// This variable is used in the heading of the calendar
		// to show the month and year

		if (preg_match_all("#".LD."date format=[\"|'](.+?)[\"|']".RD."#", $TMPL->tagdata, $matches))
		{
			foreach ($matches['1'] as $match)
			{
				$TMPL->tagdata = preg_replace("#".LD."date format=.+?".RD."#", $LOC->decode_date($match, $local_date), $TMPL->tagdata, 1);
			}
		}

		// ----------------------------------------
		//  {previous_date format="%m %Y"}
		// ----------------------------------------

		// This variable is used in the heading of the calendar
		// to show the month and year

		if (preg_match_all("#".LD."previous_date format=[\"|'](.+?)[\"|']".RD."#", $TMPL->tagdata, $matches))
		{
			foreach ($matches['1'] as $match)
			{
				$TMPL->tagdata = preg_replace("#".LD."previous_date format=.+?".RD."#", $LOC->decode_date($match, $previous_date), $TMPL->tagdata, 1);
			}
		}

		// ----------------------------------------
		//  {next_date format="%m %Y"}
		// ----------------------------------------

		// This variable is used in the heading of the calendar
		// to show the month and year

		if (preg_match_all("#".LD."next_date format=[\"|'](.+?)[\"|']".RD."#", $TMPL->tagdata, $matches))
		{
			foreach ($matches['1'] as $match)
			{
				$TMPL->tagdata = preg_replace("#".LD."next_date format=.+?".RD."#", $LOC->decode_date($match, $next_date), $TMPL->tagdata, 1);
			}
		}


		// ----------------------------------------
		//  Day Heading
		// ----------------------------------------
		/*
			This code parses out the headings for each day of the week
			Contained in the tag will be this variable pair:

			{calendar_heading}
			<td class="calendarDayHeading">{lang:weekday_abrev}</td>
			{/calendar_heading}

			There are three display options for the header:

			{lang:weekday_abrev} = S M T W T F S
			{lang:weekday_short} = Sun Mon Tues, etc.
			{lang:weekday_long} = Sunday Monday Tuesday, etc.

		*/
/*
		foreach (array('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa') as $val)
		{
			$day_names_a[] = ( ! $LANG->line($val)) ? $val : $LANG->line($val);
		}

		foreach (array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat') as $val)
		{
			$day_names_s[] = ( ! $LANG->line($val)) ? $val : $LANG->line($val);
		}

		foreach (array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday') as $val)
		{
			$day_names_l[] = ( ! $LANG->line($val)) ? $val : $LANG->line($val);
		}

		if (preg_match("/".LD."calendar_heading".RD."(.+?)".LD.SLASH."calendar_heading".RD."/s", $TMPL->tagdata, $match))
		{
			$temp = '';

			for ($i = 0; $i < 7; $i ++)
			{
				$temp .= str_replace(array( LD.'lang:weekday_abrev'.RD,
											LD.'lang:weekday_short'.RD,
											LD.'lang:weekday_long'.RD),
									 array( $day_names_a[($start_day + $i) %7],
									 		$day_names_s[($start_day + $i) %7],
									 		$day_names_l[($start_day + $i) %7]),
									  trim($match['1'])."\n");
			}

			$TMPL->tagdata = preg_replace ("/".LD."calendar_heading".RD.".+?".LD.SLASH."calendar_heading".RD."/s", trim($temp), $TMPL->tagdata);
		}


		// ----------------------------------------
		//  Separate out cell data
		// ----------------------------------------

		// We need to strip out the various variable pairs
		// that allow us to render each calendar cell.
		// We'll do this up-front and assign temporary markers
		// in the template which we will replace with the final
		// data later

		$row_start 			= '';
		$row_end 			= '';

		$row_chunk 			= '';
		$row_chunk_m		= '94838dkAJDei8azDKDKe01';

		$bookable_days 		= '';
		$bookable_days_m	= 'Gm983TGxkedSPoe0912NNk';

		$if_today 			= '';
		$if_today_m			= 'JJg8e383dkaadPo20qxEid';

		$if_bookable_days 		= '';
		$if_bookable_days_m		= 'Rgh43K0L0Dff9003cmqQw1';

		$if_not_bookable_days 	= '';
		$if_not_bookable_days_m	= 'yr83889910BvndkGei8ti3';

		$if_blank 			= '';
		$if_blank_m			= '43HDueie4q7pa8dAAseit6';


		if (preg_match("/".LD."calendar_rows".RD."(.+?)".LD.SLASH."calendar_rows".RD."/s", $TMPL->tagdata, $match))
		{
			$row_chunk = trim($match['1']);

			//  Fetch all the entry_date variable

			if (preg_match_all("/".LD."entry_date\s+format=[\"'](.*?)[\"']".RD."/s", $row_chunk, $matches))
			{
				for ($j = 0; $j < count($matches['0']); $j++)
				{
					$matches['0'][$j] = str_replace(array(LD,RD), '', $matches['0'][$j]);

					$entry_dates[$matches['0'][$j]] = $LOC->fetch_date_params($matches['1'][$j]);
				}
			}

			if (preg_match("/".LD."row_start".RD."(.+?)".LD.SLASH."row_start".RD."/s", $row_chunk, $match))
			{
				$row_start = trim($match['1']);

				$row_chunk = trim(str_replace ($match['0'], "", $row_chunk));
			}

			if (preg_match("/".LD."row_end".RD."(.+?)".LD.SLASH."row_end".RD."/s", $row_chunk, $match))
			{
				$row_end = trim($match['1']);

				$row_chunk = trim(str_replace($match['0'], "", $row_chunk));
			}

            foreach ($TMPL->var_cond as $key => $val)
            {
				if ($val['3'] == 'today')
				{
					$if_today = trim($val['2']);

					$row_chunk = str_replace ($val['1'], $if_today_m, $row_chunk);

					unset($TMPL->var_cond[$key]);
				}

				if ($val['3'] == 'bookable_days')
				{
					$if_bookable_days = trim($val['2']);

					$row_chunk = str_replace ($val['1'], $if_bookable_days_m, $row_chunk);

					unset($TMPL->var_cond[$key]);
				}

				if ($val['3'] == 'not_bookable_days')
				{
					$if_not_bookable_days = trim($val['2']);

					$row_chunk = str_replace ($val['1'], $if_not_bookable_days_m, $row_chunk);

					unset($TMPL->var_cond[$key]);
				}

				if ($val['3'] == 'blank')
				{
					$if_blank = trim($val['2']);

					$row_chunk = str_replace ($val['1'], $if_blank_m, $row_chunk);

					unset($TMPL->var_cond[$key]);
				}

				if (preg_match("/".LD."bookable_days".RD."(.+?)".LD.SLASH."bookable_days".RD."/s", $if_bookable_days, $match))
				{
					$bookable_days = trim($match['1']);

					$if_bookable_days = trim(str_replace($match['0'], $bookable_days_m, $if_bookable_days));
				}

			}

			$TMPL->tagdata = preg_replace ("/".LD."calendar_rows".RD.".+?".LD.SLASH."calendar_rows".RD."/s", $row_chunk_m, $TMPL->tagdata);

//			print("<hr/><div style=\"background-color: #FFF;\">".htmlspecialchars($TMPL->tagdata)."</div><hr/>");//TMP
		}

        // ----------------------------------------
        //  Fetch {switch} variable
        // ----------------------------------------

        // This variable lets us use a different CSS class
        // for the current day

		$switch_t = '';
		$switch_c = '';

		if ($TMPL->fetch_param('switch'))
		{
			$x = explode("|", $TMPL->fetch_param('switch'));

			if (count($x) == 2)
			{
				$switch_t = $x['0'];
				$switch_c = $x['1'];
			}
		}

        // ----------------------------------------
        //  Build the SQL query
        // ----------------------------------------

        $this->initialize();

        $this->tagparams['rdf']	= 'off';

//		$this->build_sql_query('/'.$year.'/'.$month.'/');
//		print("<hr/><div style=\"background-color: #FFF;\">SQL:<br/>".htmlspecialchars($this->sql)."</div><hr/>");//TMP

//		if ($this->sql != '')
		if (TRUE) // todo: remove conditional later
		{
			$query = $DB->query($this->sql);

			$data = array();

//########## Generate timestamps for today until maximum advance booking days #############

			$max_advance_booking_days = $this->settings['max_advance_booking_days'];

			for ($i = 0; $i <= $max_advance_booking_days; $i++)
			{
				$unix_date = mktime (0, 0, 0, date ('m'), date ('d') + $i, date ('Y'));
				$i_month = date ("m", $unix_date);
				$i_year = date ("Y", $unix_date);

				// check generated timestamp falls within currently viewed month
				if ($month == $i_month && $year == $i_year)
				{
					$rows[]['entry_date'] = $unix_date;
				}
			}

/*
			$today = time();
			$day_seconds = (24 * 60 * 60);
//			$end = $today + ($max_advance_booking_days * $day_seconds);

			$rows = array();

//			print("<hr/><div style=\"background-color: #FFF;\">");//TMP
//			print("viewing month / year: $month / $year<br/>");//TMP

			for ($i = $today; $i <= $end; $i+= $day_seconds)
			{
				$i_month = date ("m", $i);
				$i_year = date ("Y", $i);

				// check generated timestamp falls within currently viewed month
				if ($month == $i_month && $year == $i_year)
				{
					$rows[]['entry_date'] = $i;
//					print("date: ".date("j F Y", $i)."<br/>");//TMP
				}
			}
//			print("</div><hr/>");//TMP
*/

//#######################
/*
//			if ($query->num_rows > 0)
			if (sizeof($rows) > 0)
			{
				// We'll need this later

				if ( ! class_exists('Typography'))
				{
					require PATH_CORE.'core.typography'.EXT;
				}

				$TYPE = new Typography;

				// ----------------------------------------
				//  Fetch query results and build data array
				// ----------------------------------------

//				foreach ($query->result as $row)
				foreach ($rows as $row)
				{

//					print("<hr/><div style=\"background-color: #FFF;\">ROW<br/>");//TMP
//					print_r($row);//TMP
//					print("</div><hr/>");//TMP

					// ----------------------------------------
					//   Adjust dates if needed
					// ----------------------------------------

					// If the "dst_enabled" item is set in any given entry
					// we need to offset to the timestamp by an hour

				if ($row['entry_date'] != '')
					$row['entry_date'] = $LOC->offset_entry_dst($row['entry_date'], $row['dst_enabled'], FALSE);


//				print("<hr/><div style=\"background-color: #FFF;\">entry_date:<br/>".$row['entry_date']."</div><hr/>");//TMP

					// ----------------------------------------
					//  Define empty arrays and strings
					// ----------------------------------------

					$defaults = array(
										'entry_date'		=> 'a',
										'permalink'			=> 'a',
										'title_permalink'	=> 'a',
										'author'			=> 's',
										'profile_path'		=> 'a',
										'id_path'			=> 'a',
										'base_fields' 		=> 'a',
										'comment_tb_total'	=> 's',
										'day_path'			=> 's'
										);


					foreach ($defaults as $key => $val)
					{
						$$key = ($val == 'a') ? array() : '';
					}

					// ---------------------------
					//  Single Variables
					// ---------------------------

					foreach ($TMPL->var_single as $key => $val)
					{
//						print("<hr/><div style=\"background-color: #FFF;\">KEY: $key VALUE: $val</div><hr/>");//TMP

						if (isset($entry_dates[$key]))
						{
							foreach ($entry_dates[$key] as $dvar)
							{
								$val = str_replace($dvar, $LOC->convert_timestamp($dvar, $row['entry_date'], TRUE), $val);
//								print("<hr/><div style=\"background-color: #FFF;\">converted date:<br/>".$LOC->convert_timestamp($dvar, $row['entry_date'], TRUE)."</div><hr/>");//TMP
							}

							$entry_date[$key] = $val;
						}

						// ----------------------------------------
						//  parse permalink
						// ----------------------------------------

						if (ereg("^permalink", $key))
						{
							if ($FNS->extract_path($key) != '' AND $FNS->extract_path($key) != 'SITE_INDEX')
							{
								$path = $FNS->extract_path($key).'/'.$row['entry_id'];
							}
							else
							{
								$path = $row['entry_id'];
							}

							$permalink[$key] = $FNS->create_url($path, 1);
						}

						// ----------------------------------------
						//  parse title permalink
						// ----------------------------------------

						if (ereg("^title_permalink", $key) || ereg("^url_title_path", $key))
						{
							if ($FNS->extract_path($key) != '' AND $FNS->extract_path($key) != 'SITE_INDEX')
							{
								$path = $FNS->extract_path($key).'/'.$row['url_title'];
							}
							else
							{
								$path = $row['url_title'];
							}

							$title_permalink[$key] = $FNS->create_url($path, 1);

						}

						// ----------------------------------------
						//  {author}
						// ----------------------------------------

						if ($key == "author")
						{
							$author = ($row['screen_name'] != '') ? $row['screen_name'] : $row['username'];
						}
						// ----------------------------------------
						//  profile path
						// ----------------------------------------

						if (ereg("^profile_path", $key))
						{
							$profile_path[$key] = $FNS->create_url($FNS->extract_path($key).'/'.$row['member_id']);
						}

						// ----------------------------------------
						//  parse comment_path or trackback_path
						// ----------------------------------------

						if (ereg("^comment_path", $key) || ereg("^trackback_path", $key) || ereg("^entry_id_path", $key) )
						{
							$id_path[$key] = $FNS->create_url($FNS->extract_path($key).'/'.$row['entry_id']);
						}

						// ----------------------------------------
						//  parse {comment_tb_total}
						// ----------------------------------------

						if ($key == "comment_tb_total")
						{
							$comment_tb_total = $row['comment_total'] + $row['trackback_total'];
						}

						// ----------------------------------------
						//  Basic fields (username, screen_name, etc.)
						// ----------------------------------------

						if (isset($row[$val]))
						{
							$base_fields[$key] = $row[$val];
						}

						// ----------------------------------------
						//  {day_path}
						// ----------------------------------------

						if (ereg("^day_path", $key))
						{
							$d = date('d', $LOC->set_localized_time($row['entry_date']));
							$m = date('m', $LOC->set_localized_time($row['entry_date']));
							$y = date('Y', $LOC->set_localized_time($row['entry_date']));

/*
							if ($FNS->extract_path($key) != '' AND $FNS->extract_path($key) != 'SITE_INDEX')
							{
								$path = $FNS->extract_path($key).'/'.$y.'/'.$m.'/'.$d;
							}
							else
							{
								$path = $y.'/'.$m.'/'.$d;
							}
*/
/*							$path = $_SERVER['PHP_SELF'] . "?booking_date=$y-$m-$d&amp;room_id=$this->room_id&amp;action=day_view";

							$if_bookable_days = str_replace(LD.$key.RD, LD.'day_path'.RD, $if_bookable_days);

//							$day_path = $FNS->create_url($path, 1);
							$day_path = $path;
						}

					}
					// END FOREACH SINGLE VARIABLES


					// ----------------------------------------
					//  Build Data Array
					// ----------------------------------------

					$d = date('d', $LOC->set_localized_time($row['entry_date']));

					if (substr($d, 0, 1) == '0')
					{
						$d = substr($d, 1);
					}

					$data[$d][] = array(
											$TYPE->parse_type($row['title'], array('text_format' => 'lite', 'html_format' => 'none', 'auto_links' => 'n', 'allow_img_url' => 'no')),
											$row['url_title'],
											$entry_date,
											$permalink,
											$title_permalink,
											$author,
											$profile_path,
											$id_path,
											$base_fields,
											$comment_tb_total,
											$day_path
										);

				} // END FOREACH
			} // END if ($query->num_rows > 0)
		} // END if ($this->query != '')

        // ----------------------------------------
        //  Build Calendar Cells
        // ----------------------------------------

        $out = '';

		$today = getdate($LOC->set_localized_time($LOC->now));

		while ($day <= $total_days)
		{
			$out .= $row_start;

			for ($i = 0; $i < 7; $i++)
			{
				if ($day > 0 AND $day <= $total_days)
				{
					if ($if_bookable_days != '' AND isset($data[$day]))
					{
						$out .= str_replace($if_bookable_days_m, $this->var_replace($if_bookable_days, $data[$day], $bookable_days), $row_chunk);

						$out = str_replace(LD.'day_path'.RD, $data[$day]['0']['10'], $out);
					}
					else
					{
						$out .= str_replace($if_not_bookable_days_m, $if_not_bookable_days, $row_chunk);
					}

					$out = str_replace(LD.'day_number'.RD, $day, $out);


					if ($day == $today["mday"] AND $month == $today["mon"] AND $year == $today["year"])
					{
						$out = str_replace(LD.'switch'.RD, $switch_t, $out);
					}
					else
					{
						$out = str_replace(LD.'switch'.RD, $switch_c, $out);
					}
				}
				else
				{
					$out .= str_replace($if_blank_m, $if_blank, $row_chunk);
				}

        	    $day++;
			}

			$out .= $row_end;
		}

		// Garbage collection

		$out = str_replace(array($bookable_days_m,
								 $if_blank_m,
								 $if_today_m,
								 $if_bookable_days_m,
								 $if_not_bookable_days_m),
							'',
							$out);

		$output = str_replace($row_chunk_m, $out, $TMPL->tagdata);

		// output appropriate URLs
		$week_view_url = $self . "?booking_date=$this->booking_date&amp;room_id=$this->room_id&amp;action=week_view";
		$output = str_replace("{week_view_url}", $week_view_url, $output);

		$rooms_view_url = $self . "?booking_date=$this->booking_date&amp;action=rooms_view";
		$output = str_replace("{rooms_view_url}", $rooms_view_url, $output);

		// output the calendar in the place specified in the template
		$output = preg_replace("'\{calendar_view[^}]*\}(.+)\{(/|&#47;)calendar_view\}'si", "\\1", $output);

//		print("<hr/><div style=\"background-color: #FFF;\">");//TMP
//		print(htmlspecialchars($output));//TMP
//		print("</div><hr/>");//TMP

		return $output;

    } // end output_calendar_view
*/
 /*
    // ----------------------------------------
	//  Replace Calendar Variables
	// ----------------------------------------

    function var_replace($chunk, $data, $row = '')
    {
		if ($row != '')
		{
			$temp = '';

			foreach ($data as $val)
			{
				$str = $row;

				$str = str_replace(array(LD.'title'.RD,
										 LD.'url_title'.RD,
										 LD.'author'.RD,
										 LD.'comment_tb_total'.RD,
										 LD.'day_path'.RD),
									array($val['0'],
										  $val['1'],
										  $val['5'],
										  $val['9'],
										  $val['10']),
									$str);

				// Entry Date
				foreach ($val['2'] as $k => $v)
				{
					$str = str_replace(LD.$k.RD, $v, $str);
				}

				// Permalink
				foreach ($val['3'] as $k => $v)
				{
					$str = str_replace(LD.$k.RD, $v, $str);
				}

				// Title permalink
				foreach ($val['4'] as $k => $v)
				{
					$str = str_replace(LD.$k.RD, $v, $str);
				}

				// Profile path
				foreach ($val['6'] as $k => $v)
				{
					$str = str_replace(LD.$k.RD, $v, $str);
				}

				// ID path
				foreach ($val['7'] as $k => $v)
				{
					$str = str_replace(LD.$k.RD, $v, $str);
				}

				// Base Fields
				foreach ($val['8'] as $k => $v)
				{
					$str = str_replace(LD.$k.RD, $v, $str);
				}

				$temp .= $str;
			}

			$chunk = str_replace('Gm983TGxkedSPoe0912NNk', $temp, $chunk);
		}

		return $chunk;
    }
    // END*/
}
// END CLASS
?>
